-3

I trying to setting up a Xml file whose data are in class array format. The Basic class format is

OrderTemplate Class

public partial class OrderTemplate {
        public int Id { get; set; }
        public int? OrderNumberCounterId { get; set; }
        public int? SerialCounterId { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public int? Critical { get; set; }

        public Counter OrderNumberCounter { get; set; }
        public ICollection<OperationTemplate> OperationTemplate { get; set; }
        public ICollection<OrderTemplateAssemblyUnit> OrderTemplateAssemblyUnit { get; set; }


}

The Respective conversion function is given below

public async Task<IActionResult> UploadXML([FromBody] OrderTemplate[] XMLData)
        {
            try
            {


                string fileName = "OrderTemplateXMLData.xml";
                var folderName = Path.Combine("Uploads", "XMLUploads");
                var pathToSave = Path.Combine(Directory.GetCurrentDirectory(), folderName);

                var fullPath = Path.Combine(pathToSave, fileName);
                var dbPath = Path.Combine(folderName, fileName);                               

                 XDocument doc = new XDocument();
// Thinks the problem is here 
                 doc.Add(new XElement("OrderTemplate",XMLData.Select(x => new XElement("item", x)))); 

                if (Convert.ToString(XMLData).Length > 0)
                {

                    return Ok(new { dbPath });
                }
                else
                {
                    return BadRequest();
                }
            }
            catch (Exception ex)
            {
                return StatusCode(500, "Internal server error");
            }
        }
    }

CURRENT RESULT

Currently I generated the Xml file with data like this.

<?xml version="1.0" encoding="UTF-8"?>

<OrderTemplate>
  <Data>KappDmsApi.Models.OrderTemplate</Data>
  <Data>KappDmsApi.Models.OrderTemplate</Data>
</OrderTemplate>

ACTUAL RESULT

But I need to get the Data like this with the Header changed.

<OrderTemplate>
    <Order>
        <id>3</id>
        <orderNumberCounterId>1</orderNumberCounterId>
        <serialCounterId>3</serialCounterId>
        <name>Toyota FS Back</name>
        <description>Toyota FS Back</description>
        <critical>0</critical>
        <orderNumberCounter>null</orderNumberCounter>
    </Order>
    <Order>
        <id>6</id>
        <orderNumberCounterId>1</orderNumberCounterId>
        <serialCounterId>3</serialCounterId>
        <name>Toyota FS Cushion</name>
        <description>Toyota FS Cushion</description>
        <critical>0</critical>
        <orderNumberCounter>null</orderNumberCounter>
    </Order>                   
</OrderTemplate>

How to handle this situation? Is there anything to change in the above code?

Sarath Mohandas
  • 472
  • 1
  • 9
  • 25
  • Why would you want nest your `OrderTemplate` elements inside of another `OrderTemplate`? Makes no sense to me. – Jota.Toledo Aug 29 '19 at 10:52
  • I have mentioned the near the Actual Result Heading 'get the Data like this with the Header changed.' I will Re edit it.. – Sarath Mohandas Aug 29 '19 at 10:58
  • 2
    There are plenty of examples for XML serialization. Check https://learn.microsoft.com/de-de/dotnet/api/system.xml.serialization.xmlserializer?view=netcore-2.2 – Jota.Toledo Aug 29 '19 at 11:00
  • 1
    Possible duplicate of [Using XmlSerializer with an array in the root element](https://stackoverflow.com/questions/12924221/using-xmlserializer-with-an-array-in-the-root-element) – Jota.Toledo Aug 29 '19 at 11:00
  • Already gone through it. Still problem near the line doc.Add(new XElement("OrderTemplate",XMLData.Select(x => new XElement("item", x)))); Trying to use for loop to get the data from inside the model. – Sarath Mohandas Aug 29 '19 at 11:08
  • 2
    Use a serializer instead of manually creating/manipulating a XDocument.... – Jota.Toledo Aug 29 '19 at 11:09
  • I am quite confused with the serialization approach. how can I bind dynamically with attribute name and attribute value. And Save as a Xml document :( – Sarath Mohandas Aug 29 '19 at 11:52
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/198656/discussion-between-sarath-mohandas-and-jota-toledo). – Sarath Mohandas Aug 29 '19 at 11:57

1 Answers1

2

Instead of manually constructing the XML file, use a XML serializer instance.

For it to correctly generate the structure, use a wrapper-class with decorated properties as follows:

class XmlOrderTemplate {
  [XmlArray("OrderTemplate")]
  [XmlArrayItem("Order")]
  public List<OrderTemplate> Orders {get;set;}
}

using(var sw = new StreamWriter(fullPath)){
  var serializer = new XmlSerializer(typeof(XmlOrderTemplate));
   serializer.Serialize(sw, new XmlOrderTemplate {Orders = Data});
}
Jota.Toledo
  • 27,293
  • 11
  • 59
  • 73
  • Vielen Dank @ Jota.Toledo , but still this has some error like : 'Cannot serialize member of collection... because it is a interface'. I changed the above code by adding [XmlIgnore] above the Inumerable . After that my output is like – Sarath Mohandas Aug 29 '19 at 14:20
  • Vielen Dank @Jota.Toledo !!! . I got i by creating another class by removing public Counter OrderNumberCounter { get; set; } , donot know if its correct, is there any method to handle this . I will Reedit the Class in Question again. – Sarath Mohandas Aug 30 '19 at 06:11