Skip to content

.NET 10.0 XmlSerializer throws an exception on classes that worked on .NET 9 #121881

@btastic

Description

@btastic

Description

Hi dotnet team,

we are using a open source library that helps us generating electronic business documents.

This library is using class inheritance using an abstract class, which has XmlAttributes added to their virtual properties.

Inheriting classes are overriding these properties and also add the same XmlAttributes.

Running this on .NET 10 will give the following exception:

InvalidOperationException: Cannot serialize object of type 'PartyIdRef'. Base type 'PartyIdRefBase`1[PartyIdRef]' has simpleContent and can only be extended by adding XmlAttribute elements. Please consider changing XmlText member of the base class to string array.

Full stack trace:

System.InvalidOperationException: There was an error reflecting type 'Customer'.
 ---> System.InvalidOperationException: There was an error reflecting property 'PartyIdRef'.
 ---> System.InvalidOperationException: There was an error reflecting type 'PartyIdRef'.
 ---> System.InvalidOperationException: Cannot serialize object of type 'PartyIdRef'. Base type 'PartyIdRefBase`1[PartyIdRef]' has simpleContent and can only be extended by adding XmlAttribute elements. Please consider changing XmlText member of the base class to string array.
   at System.Xml.Serialization.StructMapping.SetContentModel(TextAccessor text, Boolean hasElements)
   at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
   --- End of inner exception stack trace ---
   at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
   --- End of inner exception stack trace ---
   at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
   --- End of inner exception stack trace ---
   at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportElement(TypeModel model, XmlRootAttribute root, String defaultNamespace, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(Type type, XmlRootAttribute root, String defaultNamespace)
   at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)
   at Program.<Main>$(String[] args) in C:\Users\benjamin.konsemuell\source\repos\XmlSerializerRepro\XmlSerializerRepro\Program.cs:line 4

Running the same code on .NET 9 will not throw any exceptions, and proceed with the expected operations.

Reproduction Steps

This repro only contains the bare minimum to run into this issue. I copied the classes directly from the open source project, but slimmed it down as much as possible (~80 LOC)

The project target is .net10 and if you change it to .net9.0 it will run just fine.

Expected behavior

That the same code works regardless of the target framework

Actual behavior

The same code throws an exception under .net10

Regression?

Possibly, because it worked on versions prior to .NET 10

Known Workarounds

We already refactored our fork of the library by changing the overall structure of how the inheritance works. But it involved quite a bit of work, since many classes are inheriting from it.

Configuration

Which version of .NET is the code running on?

  • .NET 9 and .NET 10

What OS and version, and what distro if applicable?

  • Windows 11

What is the architecture (x64, x86, ARM, ARM64)?

  • x64

Do you know whether it is specific to that configuration?

  • It is not

Other information

I just want to point out that this classing structure might be suboptimal, bad practice, or anything like that.

I am only raising this with the dotnet team to point out that upgrading to .NET 10 broke the behavior of the XmlSerializer, which was working completely fine in .NET 9 without a documented breaking change that touches this subject.

Thank you for your time!

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions