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.

35 comments:

Anonymous said...

Thank you very much, you saved my plenty time!

Anonymous said...

Thankyou - that sorted out my little dramas as well - awesome work. Now I can go for beer...

Lee Sy En said...

thanks you save my life too! :)

Anonymous said...

thanks ...

Lisa said...

Thank you!!!!
You helped me so much!

Anonymous said...

Samuel - thanks so much for sharing this! I've been scratching my head over a problem all morning, and your insight was the solution!

All the best from New England, USA.

Anonymous said...

Thank you!!!

Unknown said...

Hi,

I have a special issue, In client side (extjs javascript) I consume my Enable ajax WCF service.

In case of webget my service work fine
[WebGet(ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]

but when I replace webget by webinvoke all my parameters become null :@

[WebInvoke(Method="POST", ResponseFormat=WebMessageFormat.Json, BodyStyle=WebMessageBodyStyle.Bare)]

thank's in advance

Guest said...

Just wanted to add, that obfuscation will also change the names of your parameters if you don't exclude your OperationContract-interfaces. Therefore, everything will work fine in unobfuscated Debug-builds, but not on Release-builds.

Guest said...

Thanks, you saved me lots of time! I had the same problem with the wrong name. Really hard to find if you don't know what you're looking for...

Phil_steel said...

Likewise - you saved me. Won'r be forgetting that in a hurry.

Cheers..

Oisin (x0n) Grehan said...

Thanks, I already wasted a day on this but I think you just saved me another :)

guest said...

Thank you

Ragha said...

Thanks. Saved my time as well..

Jon Hardcastle said...

I lost 30mins before finding your article. Nice save.

Martin said...

fanx!

Valéry Lozat said...

Thank you very much too! But for me it was just a mismatch between service method parameter names an those of the contract.

Fatma Amin said...

Thanks so much, you save our time :)

Carlos Barros - Brasil said...

WOW!!! Saved my night of sleep!!!

theforwardway said...

Personally tested it: Improper security modes for basichttp/tcp binding can cause wcf server return null values as well.

abatishchev said...

It took 2 weeks for me to figure out that! I don't have access to the server-side contract though and work by a documentation. I never could suspect that this would be a reason!!

tonalt said...

For me the reason was that WCF service (.NET 4.0) used DataContractSerializer by default. I had .NET 2.0 client (no way to update this to newer .NET framework) that used XmlSerializer. SO finally I had to change the WCF service to use also XmlSerializer. Instructions here: http://web.archive.org/web/20130430190551/http://www.danrigsby.com/blog/index.php/2008/03/07/xmlserializer-vs-datacontractserializer-serialization-in-wcf/

Tecknoth said...

Saved us a lot of headache (and more week ends). Thanks so much

Rogério said...

Thank you very very much!

Daniel Calvanese said...

I accidentally had 'items' instead of 'item' just on my asynchronous contract. Why WCF would just transform the parameter into null instead of passing an error is beyond me.

I don't think you know how much time you probably saved, but I bet it's a lot.

Amaline J said...

If you have already added a service reference, delete that service reference completely. add a service reference newly to your client application and run the application.

The reason for the old reference name is, whenever we create a web service reference, a reference file will be created. Eventhough we update/ configure the web service the old reference name will be sustained in the reference file. When you completely delete and add the service reference a new reference file will be created, there after the values will not be null. This is the solution

Lilima Baisak said...

thank you so much it saved my job...

Samuel Jack said...

Saved your job?! Tell us more ...

sb said...

Thank you, many stomps around the building muttering to myself averted.

Pavel said...

You saved my day!!! :)

Joel said...

Years later and you're still saving lives...thanks for this post Sam!

Rui Mestre said...

Thank you! You solved my problem!

jagdishkholiya said...

Error might be because of Configuration setting changed from 3.5 to 4.0. To fix this error either change setting to previous setting or use [DataMember(IsRequired = true)] for data contract. :-)

Jasmita said...

This has been the saviour.......thanks a ton!!!

Rakesh said...

Thanks, I was scratching my head for two days because of the issue, It was because of parameter names caps mismatch between the contract and proxy.

Post a Comment