Generating WCF service proxy classes using SvcUtil

There are various ways to make calls to a WCF service from client code but this particular example uses the Microsoft svcutil.exe proxy generation tool. This is most appropriate when you want to consume a third party service and don’t have access to the service contract type declarations, but you can obtain a service metadata WSDL document from the service. To check if service metadata exchange (mex) is enabled, browse to the service and put a ?wsdl query string parameter at the end of the URL path. If it returns a WSDL XML document in the response, then metadata is enabled and you can use SvcUtil.

However, if you do have direct access to the service contract declarations (e.g. via a shared assembly) then I recommend using the WCF ChannelFactory<T> class instead of using svcutil.exe because it makes life a lot easier (see my post on how to use ChannelFactory to create re-usable proxy classes).

The following example is based on a WCF web application project using HTTP binding, but it would work just as well with a self-hosted service using another transport such as TCP.

Example service
I’ll start with a simple WCF service contract with a single operation called RegisterUser. The ServiceKnownType attribute is used to tell the WCF data contract serialiser which concrete type (in this case UserRegistration) implements the IUserRegistration interface. I haven’t shown the service implementation here, but you can just assume that it exists. Generating service proxies is all about the service contract (interface) – not the service implementation.

The UserRegistration type is a simple DTO (data transfer object) used to transfer data between a client application and the service. The DataContract and DataMember attributes which decorate the class enable the WCF data contract serialiser to convert it to and from XML.

Generating the service proxy
So now we have a service and data contract class but how can the client access them? One option is to use the .NET service model metadata tool svcutil which will generate the necessary proxy code and service configuration for us. Among the many command line switches that are available for svcutil, you can specify a namespace for the auto-generated proxy types. This is a great help in differentiating between types which are defined in the service layer when you are using them in client code. One important point about svcutil is that it should be run using the Visual Studio command prompt. Your service also needs to be hosted on IIS, IIS Express (Microsoft WebMatrix) or Cassini (Visual Studio development web server) before you can generate proxies. To ensure the service is hosted properly, try browsing to the service URL before attempting to generate the proxy.

Below is an example svcutil command line. I recommend using a fixed port number for WCF web application service host projects during development, so that you can add svcutil command lines to a batch file which can be re-run each time a service contract changes. To set a fixed port, go to service host project Properties > Web > Specific port, and enter a port number of your choice which obviously doesn’t conflict with another port in use in your solution (or within the system you are working on).

svcutil.exe http://<service url>?wsdl /t:code /n:*,Example.Client.ServiceProxies

Note the command line specifies a namespace Example.Client.ServiceProxies via the /n switch. There are additional command line switches to specify the output directory path, config file name, etc, but I have tried to keep this example as simple as possible for now. I recommend you look at Microsoft’s documentation for svcutil on the MSDN website and try out the other command line switches which are available. However the ones I’ve found most useful are:

/n:*,<namespace>  – Namespace which will apply to all generated code (and also appears in the service contract config). If you don’t specify a namespace on the command line, all generated code will belong to the global namespace which trust me, will come back and bite you when your client types and service types all become indistinguishable. Especially in your integration test projects where you will end up in project reference and type name conflict hell. The * parameter means all types will be included under the same namespace.

/d:<directory>  – Destination file path for the generated output. This is really useful for outputting the proxy code and config files to a specific location in your solution folder structure (e.g. a folder in your client project). However if several projects in a solution need the same proxy files such as a client app and a test project – which is a common situation – then direct the output to a shared folder and add the files to different projects as a link (Add > Existing Item > Add As Link).  This will prevent multiple copies of the same file being scattered throughout your solution.

/config:<config file name>  – Specific name for the generated .config file. By default it’s called output.config but obviously if you are generating proxies for more than one service in the same location, the output.config files will overwrite each other which is not very helpful. If I want separate config files, I usually specify the same name as the service, e.g. AccountService.config.

/mergeConfig  –  Rather than having a separate config file for each service, you might want all config output to a single file. This is what the /mergeConfig switch does. You can still use this together with the /config switch to specify the name of a single config ouput file for all services.  Or you can specify the name of an existing config file you want the WCF configuration to be written to (e.g. the Web.config of a web application).

Automating proxy generation
Every time a service contract or data contract interface changes, you will need to regenerate your proxy files. This can get pretty boring after a while and you don’t want to keep typing out command lines by hand because it’s slow and error-prone. So create a batch file containing the svcutil command line for each service (either all in the same batch file or separately – it’s not important) and add to your solution. I usually create a solution folder called Scripts and add all my batch files to that. Simple automation like this will save a lot of wasted time and mistakes in the long run and it also means the batch file can be added to your source version control system which is important. Every time you find yourself typing out the same thing again and again, automate it and get it under source control.

Adding svcutil output to your client project
When you run the svcutil command, it generates two files. The first is a code (.cs) file containing proxy classes for the service and any types decorated with the [DataContract] attribute which will be automatically serialised. The second is a config file containing the WCF service endpoint configuration you will need to communicate with your service. Simply add the code file to your client project in the same way you’d add any other class  file. I usually add a new folder to my client projects called something like ‘ServiceProxies’ and add the autogenerated proxy code files to this folder to stop them cluttering up the project (if your client app is using several services, then you will have separate proxy files for each one so keeping them grouped together in folder like this is a good idea).

Be aware that whenever you add a WCF service proxy file to your client project for the first time, you will also need to reference the System.Runtime.Serialization and System.ServiceModel assemblies before the client project will compile. I think the names of the assemblies make it pretty self-explanatory what their purpose is. System.ServiceModel is the core service library containing WCF types and System.Runtime.Serialization is required for data contract serialisation and deserialisation over the wire.

Next, you need to add the auto-generated service configuration to your client’s app.config or web.config file. If the client project is not a web application and doesn’t currently have a config file, then simply add an application configuration file to it. Regardless of whether it’s an app.config or web.config, the process is still the same. Copy the entire <system.serviceModel> section from the auto-generated service config and insert it into the <configuration> section of your client’s .config file. It doesn’t matter where it goes but I usually keep all my service config below existing configuration sections to stop it turning into an unreadable mess (which XML config can do very quickly).

Calling the service
The auto-generated proxy code and service configuration will both use the namespace you specified on the svcutil command line. So in this example, the UserRegistration data contract class will appear as Example.Client.ServiceProxies.UserRegistration in the client code even though its real namespace in the service layer is Example.Services.DTO.UserRegistration. This prevents any confusion, making it crystal clear to everyone that this type is a proxy of a type actually defined in the service layer.

Now to call the service from the client app, simply use the auto-generated service proxy class which will have the same name as your service but with a ‘Client’ suffix. So in this case it’s called AccountServiceClient.

When used in combination with the service configuration (which contains the address and binding responsible for creating the channel stack) the proxy will automatically marshall the call across to the hosted WCF service. As you can see, once the proxy classes and configuration are in place, the client code needed to call a service is very trivial.  This is a far cry from the difficulties of older messaging technologies and shows just how much WCF has made things easier from a developer’s perspective.

I describe how to solve compiler errors when sharing data contracts between multiple services in this separate post.

Advertisements

About Phil Munro

I have been developing commercial desktop and distributed web applications with Microsoft technologies since 1997.
This entry was posted in Automation, C#, WCF. Bookmark the permalink.