0

I am attempting to deserialize an xml string into an object, nothing strange about that. Everything was fine until I upgraded my project to .Net5.

In the upgrade, I had to add a reference to the package Microsoft.XmlSerializer.Generator, and alter the project file to add the following:

<ItemGroup>
    <DotNetCliToolReference Include="Microsoft.XmlSerializer.Generator" Version="1.0.0" />
</ItemGroup>

That allowed me to create the XmlSerializer (first error was just weird). Now, however, every call to CanDeserialize on the XmlReader return false if the class has the XmlRoot attribute. Now, I can deserialize the xml text. That does work. But why would CanDeserialize fail based on that condition?

Below is the class and the code I am using to test in a console app (.Net5).

[Serializable, XmlRoot("TestObj")]
//[Serializable]
public class TestObj
{
    public int TestVal;
}

static void Main(string[] args)
{
    var serializer = new XmlSerializer(typeof(TestObj));

    //generated by doing a test serialization of the class
    var teststr = "<TestObj xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><TestVal>2</TestVal></TestObj>";

    using (var str = new StringReader(teststr))
    using (var reader = XmlReader.Create(str))
    {
        if (serializer.CanDeserialize(reader))
            Console.WriteLine(((TestObj)serializer.Deserialize(reader)).TestVal);
        else
        {
            Console.WriteLine("Value cannot be deserialized into the given Type");
            //try it anyway
            var o = (TestObj)serializer.Deserialize(reader);
            Console.WriteLine(o.TestVal);
        }
    }
}

My workaround is just to eliminate the CanDeserialize call and wrap the deserialization in a try.. catch, but I'm still curious why this is happening.

Random
  • 1,896
  • 3
  • 21
  • 33
  • Hmm, can't reproduce using a .NET 6 fiddle, see https://dotnetfiddle.net/DwbPuZ. Why did you need to add a reference to [Microsoft.XmlSerializer.Generator](https://learn.microsoft.com/en-us/dotnet/core/additional-tools/xml-serializer-generator)? Are you actually using it to create XML serialization assemblies at build time for your types? – dbc Nov 19 '22 at 21:54
  • Also, what happens if you call [`XmlReader.MoveToContent()`](https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmlreader.movetocontent) before calling `CanDeserialize`? – dbc Nov 19 '22 at 22:03
  • I'll have to test the MoveToContent() call. I've never had to do that before. I had to add the reference because of the weird error I alluded to. Creating the XmlSerializer would fail. The error message said it couldn't find the {MyProject}.XmlSerializer.dll. Yeah, it thought XmlSerializer was in my project namespace. Even if I declared it specifically. No build error. I cleaned and restarted everything. The Generator package was the only fix I could find. – Random Nov 19 '22 at 22:51
  • Regarding the *weird error*, did the `new XmlSerializer()` constructor **actually fail**? Internally it tries to find a saved serialization DLL on disk. There is an internal exception if it's not there, but it is caught and swallowed inside the constructor and is thus harmless. See [XmlSerializer giving FileNotFoundException at constructor](https://stackoverflow.com/q/1127431). Any chance you saw the first-chance exception in the debugger or a log file and thought that was the problem, but the actual problem was something completely different? – dbc Nov 19 '22 at 22:58
  • Yes, the new constructor failed. The error specifically was referencing the namespace of the project on the XmlSerializer. Your questioning of this, however, did give me an idea to try, and I'm posting it as an answer now. – Random Nov 19 '22 at 23:01
  • @dbc, so the fiddle you posted wouldn't show the error because it doesn't reference the Generator package. I took that off my console test and CanSerialize worked as expected. – Random Nov 19 '22 at 23:08

1 Answers1

1

Okay, comments on the question from @dbc did lead me to try something else. A couple of details I left of the original question because it didn't seem relevant (due to the testing involved) is that the class I am trying to deserialize in my non-test is in a .Net Standard 2.1 library. While the project doing the deserialization is .Net5.

In the end, I got this work. I had to reference the Microsoft.XmlSerializer.Generator package in my .Net Standard based library, but not reference it in the .Net5 project.

In short, leaving the package reference off the Standard project caused one error, and including it in both caused another.

Random
  • 1,896
  • 3
  • 21
  • 33