Friday, 25 September 2009

If your WCF service is unexpectedly receiving a null parameter value, try this…

An interesting problem ate up an hour and a half of my life yesterday morning. It was all to do with a WCF service.

The parameter that I was carefully formulating on one end of the wire and passing to my service proxy was not being received by my service at the other end - instead it was getting a null value. It worked the day before - why had it stopped working overnight?

Intercepting the http traffic with the help of the wonderful Fiddler (and a useful article about Fiddlering .Net by Rick Strahl) confirmed that a serialized version of the parameter was indeed being sent down the pipe and was arriving at the server - so why wasn't my service getting it?

After much head-scratching, I thought of checking the history of our Server project in the Source code repository. That gave me the clue I needed. In the file containing the interface which defines the service's contract, I noticed that the name of the parameter on the method in question had been changed.

Now at this point I should explain that, partially inspired by this article, we have chosen to eschew the usual route of having Visual Studio create our Service proxies for us. We prefer to share the assembly containing the Service contract interfaces and Data Contract objects between the client and the server projects. This approach works very nicely most of the time. It saves us having to "Update Service Reference" every time we change the shape of the sever side, and it reduces our dependence on the magic that Visual Studio usually works on our behalf.

Where this approach does get a little bit messy is when you want to have asynchronous versions of the operations on the client side (Begin[Operation] and End[Operation] methods). Clearly we don't need these on the contract implemented by the Server, so what we end up doing is creating a copy of the Contract named something like IContractClient which contains both the synchronous and also asynchronous versions of the operations.

Now can you see where this is going?

The problem turned out to be that the name of the parameter on the client version of the contract was different to that on the server version of the contract. The message on the wire contained the client’s (incorrect) name for the parameter. So presumably, when WCF received the message, it failed to match the parameters with those expected by the method on the server, shrugged its shoulders, and passed in a null value to the method.

But the story doesn't end there. I found the client version of the contract interface, made what I thought was the necessary correction, and whilst Visual Studio was rebuilding I announced to my colleague that I'd fixed the problem. Only to find, when I tested it, that it was still broken.

More head-scratching, and Fiddlering: the old parameter name was still being passed through. Huh? Clean and Rebuild to make definitely sure the change had stuck. Still no go.

And then the final ray of light. On the client side we were using the asynchronous version of the operation, so it was the Begin[Operation] method that I'd corrected. And I'd left the synchronous version untouched.

Once that was corrected everything started working, and I could finally begin the day's work.

In conclusion, for all you googlers:

If your WCF service is receiving null values instead of the parameters you are expecting, check that the parameter names on your methods on the client version of the contract match those on the server version of the contract. And on the client side, be sure to check both the synchronous and asynchronous definitions of your methods.