0

This should be a relatively easy question I derped online for a while and still can't find a solution.

Right now my webapi returns an output like this

<Merchant>
    <Cuisine xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
        <d3p1:string>Japanese</d3p1:string>
        <d3p1:string>Korean</d3p1:string>
        <d3p1:string>French</d3p1:string>
    </Cuisine>
</Merchant>

I want it to return like this

<Merchant>
    <Cuisines>
        <Cuisine>Japanese</Cuisine>
        <Cuisine>Korean</Cuisine>
        <Cuisine>French</Cuisine>
    </Cuisines>
</Merchant>

What is the easiest way to accomplish such a task?

So basically there is two things I want to do

1)Get rid of the namespace xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" 2)change the name of outter element from

<Cuisine> 

to

<Cuisines> 

3)Change the name of inner element from

<d2p1:string>

to

<Cuisine>

And my datamember within the Merchant class is like this

[DataMember(EmitDefaultValue = false)]
public List<String> WebCuisine { get; set; }

Thank you in advnace

noobiehacker
  • 1,099
  • 2
  • 12
  • 24
  • 1
    http://stackoverflow.com/questions/12590801/remove-namespace-in-xml-from-asp-net-web-api might help – Matthew Nov 13 '13 at 00:48

2 Answers2

2

You have to use your own serializer.

  1. Create a data structure

    [XmlRoot("Merchant")]
    public class Merchant
    {
        [XmlArray("Cuisines"), XmlArrayItem("Cuisine")]
        public List<String> WebCuisine { get; set; }
    }
    
  2. Create a class inherited from XmlObjectSerializer

    public class MerchantSerializer : XmlObjectSerializer
    {
        XmlSerializer serializer;
    
        public MerchantSerializer()
        {
            this.serializer = new XmlSerializer(typeof(Merchant));
        }
    
        public override void WriteObject(XmlDictionaryWriter writer, object graph)
        {
            XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
            ns.Add("", "");
            serializer.Serialize(writer, graph, ns);
        }
    
        public override bool IsStartObject(XmlDictionaryReader reader)
        {
            throw new NotImplementedException();
        }
    
        public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName)
        {
            throw new NotImplementedException();
        }
    
        public override void WriteEndObject(XmlDictionaryWriter writer)
        {
            throw new NotImplementedException();
        }
    
        public override void WriteObjectContent(XmlDictionaryWriter writer, object graph)
        {
            throw new NotImplementedException();
        }
    
        public override void WriteStartObject(XmlDictionaryWriter writer, object graph)
        {
            throw new NotImplementedException();
        }
    }
    

As you can see I am only interested to write , but not to read. However, you can easy implement ReadObject if you need.

  1. After in WebApiConfig in public static void Register(HttpConfiguration config) you add

      config.Formatters.XmlFormatter.SetSerializer<Merchant>(new MerchantSerializer());
    

And you should get

<Merchant>
   <Cuisines>
       <Cuisine>Japanese</Cuisine>
       <Cuisine>Korean</Cuisine>
       <Cuisine>French</Cuisine>
   </Cuisines>
</Merchant>
Anton
  • 731
  • 4
  • 5
  • For creating the datastructure I get this exception -Attribute 'XmlArrayItem' is not valid on this declaration type. It is only valid on 'property, indexer, field, param, return' declarations - on the line {[XmlArray("Cuisines"), XmlArrayItem("Cuisine")] public class Merchant}. After I remove that line, code compiles but it returns exactly the same result as before, how can I fix this? – noobiehacker Nov 13 '13 at 17:48
  • Adding config.Formatters.XmlFormatter.UseXmlSerializer = true; to the WebApiConfig.cs file did the trick – noobiehacker Nov 13 '13 at 19:25
  • Sorry I just noticed Merchant should be [XmlRoot ("Merchant")] ! My copy/paste mistake. And I tested..you dont need to use xml serializer = true – Anton Nov 13 '13 at 21:05
  • Adding config.Formatters.XmlFormatter.UseXmlSerializer = true; without [XmlRoot("Merchant")] you enable another xml serializer and it changes the format so that after your custom serializer can work. So you end uo with an illusion that this is OK. Really, you don't need anything but your custom serializer!Again sorry for my stupid copy/paste mistake that deceived you. – Anton Nov 13 '13 at 22:22
0

I don't know if this will help anyone but I took the Merchant Serializer and modified it into a Generic Serializer

using System;
using System.Runtime.Serialization;
using System.Xml;
using System.Xml.Serialization;

namespace NoNamespaceXml
{

  public class GenericSerializer : XmlObjectSerializer
  {        
    #region Private Variables
    private XmlSerializer serializer;
    #endregion

    #region Constructor
    /// <summary>
    /// Create a new instance of a GenericSerializer  
    /// </summary>
    /// <param name="objectToSerialize"></param>
    public GenericSerializer (object objectToSerialize)
    {
        // If the objectToSerialize object exists
        if (objectToSerialize != null)
        {
            // Create the Serializer
            this.Serializer = new XmlSerializer(objectToSerialize.GetType());
        }
    }
    #endregion

    #region Methods

        #region IsStartObject(XmlDictionaryReader reader)
        /// <summary>
        /// This method Is Start Object
        /// </summary>
        public override bool IsStartObject(XmlDictionaryReader reader)
        {
            throw new NotImplementedException();
        }
        #endregion

        #region ReadObject(XmlDictionaryReader reader, bool verifyObjectName)
        /// <summary>
        /// This method Read Object
        /// </summary>
        public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName)
        {
            throw new NotImplementedException();
        }
        #endregion

        #region WriteEndObject(XmlDictionaryWriter writer)
        /// <summary>
        /// This method Write End Object
        /// </summary>
        public override void WriteEndObject(XmlDictionaryWriter writer)
        {
            throw new NotImplementedException();
        }
        #endregion

        #region WriteObject(XmlDictionaryWriter writer, object graph)
        /// <summary>
        /// This method Write Object
        /// </summary>
        public override void WriteObject(XmlDictionaryWriter writer, object graph)
        {
            XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
            ns.Add("", "");
            serializer.Serialize(writer, graph, ns);
        }
        #endregion

        #region WriteObjectContent(XmlDictionaryWriter writer, object graph)
        /// <summary>
        /// This method Write Object Content
        /// </summary>
        public override void WriteObjectContent(XmlDictionaryWriter writer, object graph)
        {
            throw new NotImplementedException();
        }
        #endregion

        #region WriteStartObject(XmlDictionaryWriter writer, object graph)
        /// <summary>
        /// This method Write Start Object
        /// </summary>
        public override void WriteStartObject(XmlDictionaryWriter writer, object graph)
        {
            throw new NotImplementedException();
        }
        #endregion

    #endregion

    #region Properties

        #region HasSerializer
        /// <summary>
        /// This property returns true if this object has a 'Serializer'.
        /// </summary>
        public bool HasSerializer
        {
            get
            {
                // initial value
                bool hasSerializer = (this.Serializer != null);

                // return value
                return hasSerializer;
            }
        }
        #endregion

        #region Serializer
        /// <summary>
        //  This property gets or sets the value for 'Serializer'.
        /// </summary>
        public XmlSerializer Serializer
        {
            get { return serializer; }
            set { serializer = value; }
        }
        #endregion

    #endregion

}
#endregion

}

Then all you have to do is register any types you want to use this serializser:

// Set the Serializer for certain objects
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SetSerializer<NetworkSearchResponse>(serializer);
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SetSerializer<SynxiBooleanResponse>(serializer);
Corby
  • 1
  • 2