Reputation: 83
Let's say that I have this class schema coded in c#
public class Server
{
}
public class DataServer : Server
{
public string ip { get; set; }
public string name { get; set; }
public string dataBaseName { get; set; }
}
public class ImageServer : Server
{
public string ip { get; set; }
public string name { get; set; }
public int imageNumber { get; set; }
}
public class FeedServer : Server
{
public string ip { get; set; }
public string name { get; set; }
}
public class DataCenter
{
public Server serverA { get; set; }
public Server serverB { get; set; }
}
If I got this xml in the request
<?xml version="1.0" encoding="UTF-8"?>
<DataCenter>
<ImageServer>
<ip>92.82.13.1</ip>
<name>image server</name>
<imageNumber>50</imageNumber>
</ImageServer>
<FeedServer>
<ip>82.25.87.7</ip>
<name>feed server</name>
</FeedServer>
</DataCenter>
Is this possible to serialize to this class schema? What XMLroot, XMLattributes, ... do I need in my classes?
How do i make the difference between what should go to serverA and to serverB if i don't have reference to those names?
Controller code
[HttpPost("CheckSlip")]
public async Task<bool> SaveServers([FromBody] DataCenter dataCenter)
{
// code
}
datacenter is null... I'm not able to serialize this
Upvotes: 0
Views: 1558
Reputation: 8642
You could update your DataCenter
class to be more specific:
public class DataCenter
{
public ImageServer ImageServer { get; set; }
public FeedServer FeedServer { get; set; }
}
The XmlSerializer can correctly identify the class and serialize it for you.
However, if you are trying to make the DataCenter
class agnostic i.e. it doesn't know which servers it will receive, then you might have some problems. AFAIK the serializer does not attempt to look at derived classes when attempting to create the correct class. It will only see Server
and, as the object does not fit that class it won't create it.
If you change the serverA
name to ImageServer
public class DataCenter
{
public Server ImageServer { get; set; }
public Server FeedServer{ get; set; }
}
then the serializer will create an object for you, but it will be of type Server
and you won't be able to cast that to the correct type. If you try this in code it will result in the img
variable being null
[HttpPost]
public IActionResult SaveServers([FromBody]DataCenter dataCenter)
{
var img = dataCenter.ImageServer as ImageServer;
return Ok();
}
If you want the Xml Serializer to do the work for you, then you need to be more specific about the classes you want creating.
Upvotes: 0
Reputation: 2890
The classes structure and XML Serialization attributes have to reflect the XML in order for it to work. It can be quite a time consuming task trying to create these classes manually.
I find the easiest way is to have visual studio generate the classes for you. I've knocked up a quick example below that works locally.
First. Copy the XML you wish to de-serialize. Then in visual studio add a new blank class, then select EDIT --> Paste Special --> Paste XML as Classes
This will generate the following classes below
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class DataCenter
{
private DataCenterImageServer imageServerField;
private DataCenterFeedServer feedServerField;
/// <remarks/>
public DataCenterImageServer ImageServer
{
get
{
return this.imageServerField;
}
set
{
this.imageServerField = value;
}
}
/// <remarks/>
public DataCenterFeedServer FeedServer
{
get
{
return this.feedServerField;
}
set
{
this.feedServerField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class DataCenterImageServer
{
private string ipField;
private string nameField;
private byte imageNumberField;
/// <remarks/>
public string ip
{
get
{
return this.ipField;
}
set
{
this.ipField = value;
}
}
/// <remarks/>
public string name
{
get
{
return this.nameField;
}
set
{
this.nameField = value;
}
}
/// <remarks/>
public byte imageNumber
{
get
{
return this.imageNumberField;
}
set
{
this.imageNumberField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class DataCenterFeedServer
{
private string ipField;
private string nameField;
/// <remarks/>
public string ip
{
get
{
return this.ipField;
}
set
{
this.ipField = value;
}
}
/// <remarks/>
public string name
{
get
{
return this.nameField;
}
set
{
this.nameField = value;
}
}
}
Then create an instance of an XMLSerializer and de-serialize the xml. For this exmaple I put the XML in a string var.
var xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<DataCenter>\r\n <ImageServer>\r\n <ip>92.82.13.1</ip>\r\n <name>image server</name>\r\n <imageNumber>50</imageNumber>\r\n </ImageServer>\r\n <FeedServer>\r\n <ip>82.25.87.7</ip>\r\n <name>feed server</name>\r\n </FeedServer>\r\n</DataCenter>";
XmlSerializer s = new XmlSerializer(typeof(DataCenter));
using (var reader = new StringReader(xml))
{
var item = (DataCenter)s.Deserialize(reader);
}
You will now have an object that represents the XML payload. Hope that helps
Upvotes: 1
Reputation: 641
Whenever I had to deal with XML serialization I used to take my XML file and convert it to C# classes. This tool may be useful for you: Xml2CSharp
Afterwards, you can just use this method to convert your C# class to XML and viceversa : Convert an object to an XML string
Regarding your problem, you just have to do some coding for null
checks. That is coding-logic related and there is no other way to achieve your goal.
Upvotes: 1