Recently I’ve been working on a api project where the requirement was that any data on the api service side is plain xml, stored in database as xml type column. No binding and object materialization is done on the server. However the client has to operate on clr objects. I am going to show you the solution I came to.
I have chosen the Web API 2 as the service architecture, since it perfectly fits when you want to build REST web services. A total starting point and full library for Web API 2 can be found here.
The requirement was that client application can use a web api service for retrieving and posting data and that data should be materialized into a clr object automatically. Let say the data is the following Product class
From the other side the requirement was that web service is independent on the data type it operates on. The web api service retrieves and sends the plain xml content and stores it in a database. Of course the data is somehow versioned so the service can easily validates the xml based on the data version. This is however not a topic for this post.
On the service side we only have an entity like this
Now the idea is to use xml type as a message content type, do a normal serialization/deserialization on the client side, but catch the message content on the service side before the binders come to an action and tries to materialize the message content. Let’s see how it can look on a ProductController class
As you can see we accept a HttpRequestMessage and return HttpResponseMessage, which by default are supported by the Web API engine and passed as action parameters, and operate on the content and the headers of the message. For the GET action (lines 5-11) we simply get the xml strings of items, concatenates them and put into an ArrayOfProduct xml node. This is because the xml serializer on the client side expects it to be an array of client side type element (it expects the ArrayOfProduct which is deserialized into a list of products). Then we construct the response message of it and set the content type to application/xml, so the client knows how to deserialize it. Same happens in get by id action. For POST method (lines 23-38) the body of the message is first parsed as xml document and then new xml entity is created and stored in database.
Keep in mind that for the sake of simplicity above implementation lacks the validation and security check, which should be included in production ready services.
Now we can go to the client side. Create new console application, add references to System.Net.Http and System.Net.Http.Formating and paste below code in Program.cs fileThe code should be self explanatory. One note is only required I think. In lines 18 and 33 we must explicitly say that the XmlSerializer should be used. This is because by default the DataContractSerializer is used by HttpClient which adds some special object type related namespaces to the generated xml. Since on the web service side we want to stay as much independent on the model type as possible we want to avoid such namespaces.
That’s it. The sample solution can be found in the attachement to this post.