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!