Route class:

[Serializable] [XmlRoot("Main")] public class MainClass { public MainClass() { Parents = new List<MyParent>(); } [XmlElement("Parent")] public List<MyParent> Parents { get; set; } } 

There is a parent class:

 [Serializable] [XmlRoot("Parent")] public class MyParent { public enum myEnum : int { One, Two, Three }; [XmlAttribute("Id")] public string Id { get; set; } [XmlAttribute("Name")] public string Name { get; set; } } 

There is a class extending it:

 [Serializable] [XmlRoot("Parent")] public class MyChild : MyParent { public MyChild() { Child = new List<InnerParameter>(); } [XmlElement("Child")] public List<InnerParameter> Child { get; set; } } 

This class reveals that inside the Child tag :

 [Serializable] [XmlRoot("Child")] public class InnerParameter { public InnerParameter() { } [XmlText] public string Value { get; set; } } 

Then, I try to serialize:

 MainClass newMainXml = new MainClass(); newMainXml.Parents = new List<MyParent>(); MyChild ch = new MyChild (); ch.Id = "123"; ch.Name = "Stefani"; InnerParameter parameter = new InnerParameter(); parameter.Value = "MyText"; ch.Child.Add(parameter); newMainXml.Parents.Add(ch); XmlSerialization.TrySerializeObjectToXmlString(newMainXml, out result); 

I want the following XML on output:

 <Main> <Parent Id="123" Name="Stefani"> <Child>MyText</Child> </Parent> </Main> 

I get a serialization error:

Generating XML document. The type MyChild was not expected. Use the XmlInclude or SoapInclude attribute to specify types.

Tell me please, what am I doing wrong in the formation of xml? Why is serialization not working? ( There is a great suspicion that the matter here is in the inheritance and dependence of classes among themselves. Probably, I must say that MyChild is not the only class that extends MyParent ... )

PS: it looks like the situation is almost like mine: XML serialization of an object with a field of type Object C #

  • one
    How about adding text to the error and the grid? - andreycha
  • 2
    XmlSerialization.TrySerializeObjectToXmlString does not look like a standard method. Show its implementation. - Pavel Mayorov
  • @andreycha, edited the question. Added error text. - neo
  • Yes, you have the situation in a similar issue. You need to add XmlInclude . - andreycha

3 answers 3

Apparently TrySerializeObjectToXmlString implemented like this:

 private static void TrySerializeObjectToXmlString(MainClass ch, out string result) { StringBuilder sb = new StringBuilder(); using (var writer = new StringWriter(sb)) { XmlSerializer s = new XmlSerializer(typeof(MainClass)); s.Serialize(writer, ch); } result = sb.ToString(); } 

With such an implementation, it falls exactly with the error from the question.

In this case, adding XmlInclude to the MyParent type should suffice:

 [Serializable] [XmlRoot("Command")] [XmlInclude(typeof(MyChild))] public class MyParent { public enum myEnum : int { One, Two, Three }; [XmlAttribute("Id")] public string Id { get; set; } [XmlAttribute("Name")] public string Name { get; set; } } 
  • Did not help ..... - neo
  • @neo I completely copied your code from the question, added the TrySerializeObjectToXmlString method, launched it - it crashed. Added XmlInclude - earned. Here is a link to gist with the full code of the example: gist.github.com/PashaPash/e725653863c615437be7 - PashaPash
  • it seems that the problem is not hidden in this part of the code ... Now I will try to recreate a more complex picture in the question ... - neo
  • edited the question. - neo
  • The @neo code from the updated question is not corporate. and if you add parentheses, it still works. give a minimal reproducible example - PashaPash

Try this :)

 internal class Program { private static void Main(string[] args) { var ch = new MyChild(); ch.Id = "123"; ch.Name = "Stefani"; var parameter = new InnerParameter(); parameter.Value = "MyText"; ch.Child.Add(parameter); string result = XmlHelper.ObjectToXmlString(ch); } public static class XmlHelper { public static string ObjectToXmlString(object obj) { var xmlSerializer = new XmlSerializer(obj.GetType()); using (var textWriter = new StringWriter()) { xmlSerializer.Serialize(textWriter, obj); return textWriter.ToString(); } } } } 

Because The question has been edited - here is a new solution to correcting the error that your code gives:

 [Serializable, XmlInclude(typeof(MyChild))] [XmlRoot("Main")] 

Just add an XmlInclude (typeof (MyChild)) for the MainClass class, since he doesn't know anything about MyChild; this will allow him to recognize MyChild during the serialization process.

  • four
    I am sure the author of the question would appreciate your comments and clarification of the idea of ​​a solution. - Nicolas Chabanovsky
  • @NicolasChabanovsky, yes, in principle, without explanation everything is quite clear. The ObjectToXmlString (object obj) function is very similar to the one I use, I just didn’t give its code. - neo
  • Thanks for the clarifications! - Nicolas Chabanovsky

The problem is really solved by adding [XmlInclude (typeof (MyChild))] in this way:

 [Serializable] [XmlRoot("Parent")] [XmlInclude(typeof(MyChild))] public class MyParent { public enum myEnum : int { One, Two, Three }; [XmlAttribute("Id")] public string Id { get; set; } [XmlAttribute("Name")] public string Name { get; set; } } 

My mistake was that (for comparison) I had written this:

 [Serializable] [XmlRoot("Parent")] [XmlInclude(typeof(MyChild)), XmlInclude(typeof(HisChild)), XmlInclude(typeof(HerChild))] public class MyParent { public enum myEnum : int { One, Two, Three }; [XmlAttribute("Id")] public string Id { get; set; } [XmlAttribute("Name")] public string Name { get; set; } } 

However, as I said, MyChild is not the only class implementing MyParent , and these heirs must also be serialized. Here is a good article: Xml Serialization and Inheritance