Background
I wrote a WCF service a while ago that makes heavy use of custom operation invokers, error handlers, and behaviors - many of which heavily rely on the input message being of a certain type, or the message's base message type (each DataContract inherits from a base class and a number of interfaces). There are also many unit and integration tests set up for the various interfaces and classes involved. In addition, the software has to go through a vigorous sign off process every time it is modified, and rewriting the service layer is not my idea of fun.
It is currently configured to allow JSON and SOAP requests to come in.
Problem
A client wishes to POST to this service, using a application/x-www-form-urlencoded content-type, due to restrictions in their legacy software. Normally, the service would accept a JSON request that looks like this:
{
"username":"jeff",
"password":"mypassword",
"myvalue":12345
}
And the application/x-www-form-urlencoded message body that the client can send looks a bit like this:
username=jeff&password=mypassword&myvalue=12345
Alternatively, the client has informed me that they could format the message as follows (if its useful):
myjson={username:jeff,password:mypassword,myvalue:12345}
Also consider that the service contrract looks like this:
[ServiceContract(Namespace = "https://my.custom.domain.com/")]
public interface IMyContract {
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, UriTemplate = "process")]
MyCustomResponse Process(MyCustomRequest req);
}
I would like to keep MyCustomRequest, and avoid replacing it with a Stream (as per the below links).
I have found a number of posts that suggest how to achieve this using a Stream OperationContract parameter, but in my particular instance it will be a lot of work to change the type of the OperationContract's parameter. The below posts go into some detail:
Using x-www-form-urlencoded Content-Type in WCF
Best way to support "application/x-www-form-urlencoded" post data with WCF?
http://www.codeproject.com/Articles/275279/Developing-WCF-Restful-Services-with-GET-and-POST
Though I haven't found anything particularly useful in any of them.
Question
Is there any way that I can intercept the message before it reaches the operation contract, and convert it from a the client's input to my custom classes, then have the rest of the application treat it as per normal?
Custom Message inspector? Operation selector? It's been a while since I got into the guts of WCF, so I'm a little rusty right now. I spent a while looking for the below image, as I remember using it to remind me of the call stack - if it's still relevant!
So, I solved this using a message inspector. It's not pretty, but it works for my case!
I then created an endpoint behavior and added it via WCF configuration:
Here's the excerpt of the config changes:
QueryStringSerializer.Deserialize() deserializes a querystring into a DataContract (based on the DataMember.Name attribute, or the property name if the DataMember attribute does not exist).