Namespaces and deserialization issue
- by CaffGeek
UPDATE:  You can run the code at the end of this to recreate and see the error I am having and hopefully solve it!
UPDATE2: It's not the removal of the xmlns="" that's the issue... as you can remove it from the initial xml string.  The problem is with the [XmlType(TypeName = "Systems")] somehow causing it to be added...
UPDATE3: Turns out the problem is in here, I need to set the TypeName based on what is in the existing, XmlTypeAttribute if it already exists on the class....
    xmlAttributes.XmlType = new XmlTypeAttribute
    {
        Namespace = ""
    };
I get the following XML as a string from a webservice
<Systems xmlns="">
  <System id="1">
    <sys_name>ALL</sys_name>
  </System>
  <System id="2">
    <sys_name>asdfasdf</sys_name>
  </System>
  <System id="3">
    <sys_name>fasdfasf</sys_name>
  </System>
  <System id="4">
    <sys_name>asdfasdfasdf</sys_name>
  </System>
</Systems>
I then execute this, to convert it to an object
result = XElement.Parse(xmlResult.OuterXml).Deserialize<AwayRequestSystems>();
Strangely though, in the Deserialize method, while the RemoveAllNamespaces works and returns the xml without the namespace
I get the error <Systems xmlns=''> was not expected. in the catch when return (T) serializer.Deserialize(reader); executes!
Why is it doing this?  The xmlns is GONE!!!
EXECUTABLE CODE!  (Just put it in a test project)
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Xml.Serialization;
namespace DeserializationTest
{
    [TestClass]
    public class UnitTest1
    {
    public TestContext TestContext { get; set; }
    [TestMethod]
    public void RemoveXmlnsFromSystems()
    {
        var xml = XElement.Parse(@"<Systems xmlns="""">
                      <System id=""1"">
                        <sys_name>ALL</sys_name>
                      </System>
                      <System id=""2"">
                        <sys_name>ePO</sys_name>
                      </System>
                      <System id=""3"">
                        <sys_name>iEFT</sys_name>
                      </System>
                      <System id=""4"">
                        <sys_name>Away Requests</sys_name>
                      </System>
                      <System id=""5"">
                        <sys_name>RP3</sys_name>
                      </System>
                    </Systems>");
        var systems = xml.Deserialize<AwayRequestSystems>();
        Assert.IsInstanceOfType(systems, typeof(AwayRequestSystems));
        var xmlnsFree = xml.RemoveAllNamespaces();
        var str = xmlnsFree.ToString();
        Debug.WriteLine(str);
        Assert.AreNotEqual("Error", xmlnsFree.Name.ToString(), "Serialization Error");
        Assert.IsFalse(str.Contains("xmlns"), "Xmlns still exists");
    }
    }
    [XmlType(TypeName = "Systems")]
    public class AwayRequestSystems : List<AwayRequestSystem> { }
    [XmlType(TypeName = "System")]
    public class AwayRequestSystem
    {
    [XmlAttribute("id")]
    public int ID { get; set; }
    [XmlElement("sys_name")]
    public string Name { get; set; }
    }
    public static class XmlSerializerFactory
    {
    private static Dictionary<Type, XmlSerializer> _serializers = new Dictionary<Type, XmlSerializer>();
    public static void ResetCache()
    {
        _serializers = new Dictionary<Type, XmlSerializer>();
    }
    public static XmlSerializer GetSerializerFor(Type typeOfT)
    {
        if (!_serializers.ContainsKey(typeOfT))
        {
        var xmlAttributes = new XmlAttributes();
        var xmlAttributeOverrides = new XmlAttributeOverrides();
        Debug.WriteLine(string.Format("XmlSerializerFactory.GetSerializerFor(typeof({0}));", typeOfT));
        xmlAttributes.XmlType = new XmlTypeAttribute
        {
            Namespace = ""
        };
        xmlAttributes.Xmlns = false;
        var types = new List<Type> { typeOfT, typeOfT.BaseType };
        foreach (var property in typeOfT.GetProperties())
        {
            types.Add(property.PropertyType);
        }
        types.RemoveAll(t => t.ToString().StartsWith("System."));
        foreach (var type in types)
        {
            if (xmlAttributeOverrides[type] == null)
            xmlAttributeOverrides.Add(type, xmlAttributes);
        }
        var newSerializer = new XmlSerializer(typeOfT, xmlAttributeOverrides);
        //var newSerializer = new XmlSerializer(typeOfT, xmlAttributeOverrides, types.ToArray(), new XmlRootAttribute(), string.Empty);
        //var newSerializer = new XmlSerializer(typeOfT, string.Empty);
        _serializers.Add(typeOfT, newSerializer);
        }
        return _serializers[typeOfT];
    }
    }
    public static class XElementExtensions
    {
    public static XElement RemoveAllNamespaces(this XElement source)
    {
        if (source.HasAttributes)
        source.Attributes().Where(a => a.Name.LocalName.Equals("xmlns")).Remove();
        return source.HasElements
               ? new XElement(source.Name.LocalName,
                      source.Attributes()/*.Where(a => !a.Name.LocalName.Equals("xmlns"))*/,
                      source.Elements().Select(el => RemoveAllNamespaces(el))
                 )
               : new XElement(source.Name.LocalName)
                 {
                 Value = source.Value
                 };
    }
    }
    public static class SerializationExtensions
    {
    public static XElement Serialize(this object source)
    {
        try
        {
        var serializer = XmlSerializerFactory.GetSerializerFor(source.GetType());
        var xdoc = new XDocument();
        using (var writer = xdoc.CreateWriter())
        {
            serializer.Serialize(writer, source, new XmlSerializerNamespaces(new[] { new XmlQualifiedName("", "") }));
        }
        var result = (xdoc.Document != null) ? xdoc.Document.Root : new XElement("Error", "Document Missing");
        return result.RemoveAllNamespaces();
        }
        catch (Exception x)
        {
        return new XElement("Error", x.ToString());
        }
    }
    public static T Deserialize<T>(this XElement source) where T : class
    {
        //try
        //{
        var serializer = XmlSerializerFactory.GetSerializerFor(typeof(T));
        var cleanxml = source.RemoveAllNamespaces();
        var reader = cleanxml.CreateReader();
        return (T)serializer.Deserialize(reader);
        //}
        //catch (Exception x)
        //{
        //    return null;
        //}
    }
    }
}