Search code examples
xmlserializationxml-namespacesrestsharpxmlserializer

Omit xmlns and d4p1 from DotNetXmlSerializer


I send a Webrequest using

    var request = new RestRequest(string.Format(url, config.ApiLocale), Method.POST)
        {
            RequestFormat = DataFormat.Xml,
            XmlSerializer = new RestSharp.Serializers.DotNetXmlSerializer("")
        };

My request is built like this:

    List<RequestParam> listParams = new List<RequestParam>()
    {
        new RequestParam("Foo1"),
        new RequestParam("Foo2"),
        new RequestParam(12345)
    };

    request.AddBody(new XmlRequest
    {
        MethodName = "api.Testcall",
        ListParams = listParams
    });

My classes:

    using RestSharp.Deserializers;
    using System;
    using System.Collections.Generic;
    using System.Xml.Serialization;

    namespace Testcall
    {
        [XmlRoot("methodCall")]
        public class XmlRequest
        {
            [XmlElement(ElementName = "methodName")]
            public string MethodName { get; set; }
            [XmlArray(ElementName = "params")]
            [XmlArrayItem("param")]
            public List <RequestParam> ListParams { get; set; }

        } 

        public class RequestParam
        {
            [XmlElement(ElementName = "value")]
            public ParamFather Value { get; set; }

            public RequestParam() { }
            public RequestParam(String PassValue)
            {
                Value = new StringParam(PassValue);
            }
            public RequestParam(int PassValue)
            {
                Value = new IntParam(PassValue);
            }
            public RequestParam(Boolean PassValue)
            {
                Value = new BoolParam(PassValue);
            }
        }

        [XmlInclude(typeof(StringParam))]
        [XmlInclude(typeof(BoolParam))]
        [XmlInclude(typeof(IntParam))]
        public class ParamFather
        {
            [XmlElement(ElementName = "father")]
            public String Content { get; set; }
        }

        public class StringParam : ParamFather
        {
            [XmlElement(ElementName = "string")]
            public String StringContent { get; set; }
            public StringParam() { }
            public StringParam(String Content)
            {
                StringContent = Content;
            }
        }
    }

But the Serializer returns an XML including Strange d4p1 and xmlns-Tags. Those I want to omit! I just need the plain xml not wearing any tags.

    <methodCall>
        <methodName>api.Testcall</methodName>
        <params>
            <param>
                <value d4p1:type=\"StringParam\" xmlns:d4p1=\"http://www.w3.org/2001/XMLSchema-instance\">
                    <string>Foo1</string>
                </value>
            </param>
            <param>
                <value d4p1:type=\"StringParam\" xmlns:d4p1=\"http://www.w3.org/2001/XMLSchema-instance\">
                    <string>Foo2</string>
                </value>
            </param>
            <param>
                <value d4p1:type=\"IntParam\" xmlns:d4p1=\"http://www.w3.org/2001/XMLSchema-instance\">
                    <int>12345</int>
                </value>
            </param>
        </params>
    </methodCall>

I tried using the classic XMLSerializer instead but failed. Is it possible to do this with the DotNetXmlSerializer at all?


Solution

  • Finally I solved the problem by switching to the standard XmlSerializer.

        [XmlRoot("methodCall")]
        public class XmlRequest
        {
            [XmlElement(ElementName = "methodName")]
            public string MethodName { get; set; }
            [XmlArray(ElementName = "params")]
            [XmlArrayItem("param")]
            public List <RequestParam> ListParams { get; set; }
    
            public string ToXML()
            {
                using (var stringwriter = new System.IO.StringWriter())
                {
                    using (var xmlwriter = XmlWriter.Create(stringwriter, new XmlWriterSettings { OmitXmlDeclaration = true }))
                    {
                        XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", "");
                        new XmlSerializer(this.GetType()).Serialize(xmlwriter, this, ns);
                    }
                    return stringwriter.ToString();
                }
            }
        }
    

    I am calling it like this:

        List<RequestParam> listParams = new List<RequestParam>()
        {
            new RequestParam("user"),
            new RequestParam("password"),
            new RequestParam(true),
            new RequestParam(123) 
        };
        request.Parameters.Clear();
    
        XmlRequest reqObject = new XmlRequest
        {
            MethodName = "api.Testcall",
            ListParams = listParams
        };
        string rawXml = reqObject.ToXML();
        request.AddParameter("application/xml", rawXml, ParameterType.RequestBody);
    

    Notice that I am now using request.AddParameter instead of request.AddBody which I used before. So I have more control, Creating a String by the standard XmlSerializer. The OmitXmlDeclaration suppresses the encoding and the standard start of xml-Document. My Classes changed also:

        public class RequestParam
        {
            [XmlElement(ElementName = "value")]
            public Alterable Value { get; set; }
    
            public RequestParam() { }
            public RequestParam(int number)
            {
                Value = new Alterable(number);
            }
            public RequestParam(String str)
            {
                Value = new Alterable(str);
            }
            public RequestParam(Boolean boo)
            {
                Value = new Alterable(boo);
            }
        }
    
        public class Alterable
        {
            [XmlElement(DataType = "string",Type = typeof(string)),
             XmlElement(DataType = "int",Type = typeof(int)),
             XmlElement(DataType = "boolean",Type = typeof(Boolean))]
             public object Changeable { get; set; }
             public Alterable() { }
             public Alterable(int number)
             {
                 Changeable = number;
             }
             public Alterable(string str)
             {
                 Changeable = str;
             }
             public Alterable(Boolean boo)
             {
                 Changeable = boo;
             }
        }
    

    My Alterable class can take strings, ints and booleans and prints them correctly into the XML. Hope this helps someone having the same issues.

    The Result:

        <methodCall>
           <methodName>api.Testcall</methodName>
           <params>
              <param>
                 <value>
                    <string>user</string>
                 </value>
              </param>
              <param>
                 <value>
                    <string>password</string>
                 </value>
              </param>
              <param>
                 <value>
                    <boolean>true</boolean>
                 </value>
              </param>
              <param>
                 <value>
                    <int>123</int>
                 </value>
              </param>
           </params>
        </methodCall>