ASP.NET MVC WebApi and Xml serialization

In our project we use XSD to describe messages over project boundaries. This way we can all develop in our own speed. The XSD describes XML with attributes and elements. ASP.NET MVC WebApi supports this, but not out-of-the-box. Default the datacontract serializer is used and that uses elements.

Consider the message class

// the (simplified) class generated from the xsd
[Serializable]
public class HelloWorld {
    [System.Xml.Serialization.XmlAttribute]
    public int Id { get; set; }
    [System.Xml.Serialization.XmlAttribute]
    public string Sender { get; set; }
}

Using all the defaults and the HttpClient code below

using (var client = new HttpClient()) {
    var task = client.PostAsXmlAsync<HelloWorld>(uri, 
        new HelloWorld { Id = 10, Sender = "eric" });
    task.Wait();
    // do something with task.Result.IsSuccessStatusCode
}

The message send over the wire (caught with Fiddler) is nothing like the expected XML. If we would validate using the XSD this would fail.

<HelloWorld xmlns:i="http://www.w3.org/2001/XMLSchema-instance" 
            xmlns="http://schemas.datacontract.org/2004/07/Messsages">
<_x003C_Id_x003E_k__BackingField>10</_x003C_Id_x003E_k__BackingField>
<_x003C_Sender_x003E_k__BackingField>eric</_x003C_Sender_x003E_k__BackingField>
</HelloWorld>

To get the correct message we must use the Xml Serializer. This can be set on the HttpClient

using (var client = new HttpClient()) {
    var task = client.PostAsync<HelloWorld>(uri,
        new HelloWorld { Id = 10, Sender = "eric" },
        new XmlMediaTypeFormatter { UseXmlSerializer = true }
    );
    task.Wait();
    // do something with task.Result.IsSuccessStatusCode
}

This will generate the correct Xml

<HelloWorld xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
            Id="10" 
            Sender="eric" />

The message is now in the correct Xml, but the server cannot read it since that is still using the default. Change the server side serializer in the config and you’re good to go.

public static class WebApiConfig {
    public static void Register(HttpConfiguration config) {
        // Web API configuration and services
        config.Formatters.XmlFormatter.SetSerializer<HelloWorld>(
                new XmlSerializer(typeof(HelloWorld)));
        // Web API routes
        config.MapHttpAttributeRoutes();
        // other code ....
    }
}

Even with this change in configuration the Json format can be used. Hurrah for ASP.NET MVC WebApi!

About erictummers

Working in a DevOps team is the best thing that happened to me. I like challenges and sharing the solutions with others. On my blog I’ll mostly post about my work, but expect an occasional home project, productivity tip and tooling review.
This entry was posted in Development and tagged , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.