csharper
csharper

Reputation: 83

Serialize xml request in c# controller

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

Answers (3)

Simply Ged
Simply Ged

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

Wheels73
Wheels73

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

k1dev
k1dev

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

Related Questions