Sunday, August 09, 2009
WCF Service Contract and XML Serialization
I am building a Service using the WCF REST Starter Kit. This Service contains a method that accepts a complex type as input, it then deserializes the object into it’s concrete type.
Here’s how a service call looks like
using (HttpClient client = new HttpClient())
{
RequestObject req = new RequestObject { FirstName = "John", LastName = "Doe", Email="johndoe@somecompany.com"};
HttpContent body = HttpContentExtensions.CreateXmlSerializable<RequestObject>(req);
HttpResponseMessage resp = client.Post("http://localhost:1575/Web/Service.svc/SendMail", body);
Response.Write(resp.Content.ReadAsString());
}
What the above does is simply prepare a RequestObject, call a SendMail method on the service using the HttpClient, read and print the response, nothing fancy.
Here’s how the service looks like
[WebHelp(Comment = "Sample description for SendMail")]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, RequestFormat =
WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml,UriTemplate = "SendMail")]
[OperationContract]
public RequestObject SendMail(RequestObject request)
{
return new RequestObject()
{
FirstName = request.FirstName, LastName = request.LastName,Email = request.Email
};
}
Notice what I’m doing is preparing the same RequestObject and simply pass it as the response.
As you’d expect I’m suppose to get the following response in the browser.
- <RequestObject>
<FirstName>John</FirstName>
<LastName>Doe</LastName>
<Email>johndoe@somecompany.com</Email>
</RequestObject>
But the response I receive is similar to this
<RequestObject>
<FirstName i:nil="true" />
<LastNameName i:nil="true" />
<Email>johndoe@somecompany.com</Email>
</RequestObject>
After a few hours of trying it occurred to me that XML Serialization is done in the alphabetical order if no ordering is specified even if the properties in the class are not in the alpha-order. (arrgh. If only I had used the Paste XML as Type as demo’ed in this screencast by Aaron Skonnard)
So to make it work I had to change the RequestObject class in both places to look like the following.
public class RequestObject
{
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Labels: C#, REST, WCF, WCF Service