none
IXmlSerializable with empty elements in WCF RRS feed

  • Question

  • I have IXmlSerializable class used both on client and server side.

    In WriteXml it writes an element with one attribute and without content.
    But when ReadXml is called element is not empty and has end tag.

        public class CommonType : IXmlSerializable
        {
            public System.Xml.Schema.XmlSchema GetSchema()
            {
                return null;
            }
    
            public void WriteXml(System.Xml.XmlWriter writer)
            {
                // write empty element: <Element Attr="123" />
                writer.WriteStartElement("Element");
                writer.WriteAttributeString("Attr", "123");
                writer.WriteEndElement();
            }
    
            public void ReadXml(System.Xml.XmlReader reader)
            {
                reader.ReadStartElement();
    
                if (!reader.IsEmptyElement)
                    throw new Exception("Element is not empty"); // Error, xml is: <Element Attr="123"></Element>
    
                string arrt = reader.GetAttribute("Attr");
                reader.ReadStartElement("Element");
            }
    
            #endregion
        }
    I checked serialization by XmlSerializer and DataContractSerializer and it works normally.
    But when i pass it through WCF service i get error. What's the difference? Why end element is being written?
    Wednesday, July 25, 2012 7:55 PM

All replies

  • It looks like that issue is in NetTcpBinding.

    Here's full code of sample:

    using System;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.Xml.Serialization;
    
    namespace CommonTypeTest
    {
        class Program : IService
        {
            static void Main(string[] args)
            {
                if (Console.ReadKey().KeyChar == 's')
                {
                    ServiceHost host = new ServiceHost(typeof(Program));
                    host.AddServiceEndpoint(typeof(IService), new WSHttpBinding(), "http://localhost:8081");
                    host.AddServiceEndpoint(typeof(IService), new NetTcpBinding(), "net.tcp://localhost:8080");
                    host.Open();
                    Console.WriteLine();
                    Console.WriteLine("Started");
                }
                else
                {
                    Check(new WSHttpBinding(), "http://localhost:8081");
                    Check(new NetTcpBinding(), "net.tcp://localhost:8080");
                }
    
                Console.ReadLine();
            }
    
            static void Check(Binding binding, string address)
            {
                try
                {
                    Console.WriteLine(address);
                    ServiceClient httpClient = new ServiceClient(binding, address);
                    httpClient.Test();
                    Console.WriteLine("OK");
                }
                catch (Exception e)
                {
                    Console.WriteLine("Error: " + e.Message);
                }
            }
    
            public CommonType Test() { return new CommonType(); }
        }
    
        [ServiceContract]
        public interface IService
        {
            [OperationContract]
            CommonType Test();
        }
    
        public class ServiceClient : ClientBase<IService>
        {
            public ServiceClient(Binding binding, string address)
                : base(binding, new EndpointAddress(address))
            {
            }
    
            public CommonType Test() { return Channel.Test(); }
        }
    
        public class CommonType : IXmlSerializable
        {
            public System.Xml.Schema.XmlSchema GetSchema() { return null; }
    
            public void WriteXml(System.Xml.XmlWriter writer)
            {
                // write empty element: <Element Attr="123" />
                writer.WriteStartElement("Element");
                writer.WriteAttributeString("Attr", "123");
                writer.WriteEndElement();
            }
    
            public void ReadXml(System.Xml.XmlReader reader)
            {
                reader.ReadStartElement();
    
                if (!reader.IsEmptyElement)
                    throw new Exception("Element is not empty"); // Error in NetTcpBinding, xml is: <Element Attr="123"></Element>
    
                string attr = reader.GetAttribute("Attr");
                reader.ReadStartElement("Element");
            }
        }
    }
    

    For WSHttpBinding it works well, for NetTcpBinding it crashes.
    What's wrong with NetTcpBinding data serialization?

    Thursday, July 26, 2012 6:27 AM