Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / operating-systems / Windows

Disappearing Parameter Value of a Web Reference

4.27/5 (4 votes)
28 Sep 2011CPOL3 min read 9.6K  
This post helps us to understand the mechanism behind creating a proxy class while adding a Web Reference. More importantly it concentrates on the parameter values that get missed while calling a web service method.

Introduction

This post helps us to understand the mechanism behind creating a proxy class while adding a Web Reference. This post mainly concentrates on the parameter values that get missed while calling a web service method.

Background

While adding a Web Reference to our project or using wsdl.exe to consume WCF, and while calling the methods exposed in the reference with parameters; we generally get to the state where we don’t understand why our data is not sent or rather sent as zero to the service even when we provide it.

For example; let's consider the following:

C#
[OperationContract]
int GetEmployeeDetails (Consumer c);
//The operation is using the following data contract:
[DataContract]
public class Consumer
{
   [DataMember]
   public int consumerId;
   [DataMember]
   public int consumerZipCode;
}

If you use “Add Web Reference” to this service, you will get a proxy along with a “Consumer” class. You may use the proxy like this:

C#
Consumer c = new Consumer();
c.consumerId = 19089;
c.consumerZipCode = 48397;
Employee emp = proxy.GetEmployeeDetails(c);

However, this won’t work – the consumerId and consumerZipCode items will be zero on the service side! This is because the items are not transmitted from the client to the service.

A Closer Look

To see it even more closely, let us look at the generated consumer class on the client side. It will look similar to the following:

C#
public class Consumer
{
public int consumerId { /* get/set code omitted… */ };
public bool consumerIdSpecified;
public int consumerZipCode { /* get/set code omitted… */ };
public bool consumerZipCodeSpecified;
}

Did you notice these extra booleans? Where do they come from and what do they do?

The answer is; this is the schema that the WCF data contract serializer generates by default. Because of the way its versioning model works, the serializer generates all data members as optional elements. The right way to use the proxy is as follows:

C#
Consumer c = new Consumer();
c.consumerId = 19089;
c.consumerIdFromSpecified = true;
c.consumerZipCode = 48397;
c.consumerZipCodeSpecified = true;
Employee emp = proxy.GetEmployeeDetails(c);

Now, even when you know about this, you may find this disturbing to always have to write such code. Instead, you can prevent the —Specified members from being generated by marking the data members as required instead of optional:

C#
[DataContract]
public class consumer
{
[DataMember(IsRequired=true)]
public int consumerId;
[DataMember(IsRequired=true)]
public int consumerZipCode;
}

Always have in mind that WCF will throw an exception if a required data member is missing. It is usually fine to mark all data members as required in a first version of a data contract. However, if you add a new data member (e.g. if we also want to add an “int consumerPhone” to our contract in v2), it should not be marked as required – otherwise, v1 clients will not be able to talk to v2 services (or vice versa, depending on where the data contract is used).

This is otherwise called as lax versioning in WCF Versioning Terms.To know more about WCF Versioning, visit http://www.bloggingbunk.com/2011/08/wcf-versioning/.

Another solution apart from the above is to change the generated proxy code on the client side. You could specify default values of “true” for the —Specified members, or you could modify the property setter for each member (e.g. consumerId) to set the corresponding —Specified member (e.g. consumerIdSpecified) to true whenever that property is set.

There are many circumstances in which modifying the generated proxy code is unacceptable – e.g. when you expect the service to change and thus expect to have to regenerate the proxy code often. In this situation, you can take advantage of the “partial class” feature to add a helper method to do the property setting work.

Conclusion

Therefore the recommendations will be to Add Service Reference while consuming a WCF service.

History

  • 28th September, 2011: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)