Andrew Arnott

News from my corner of the Visual Studio Connected Experience team, programming tips, and solutions to common programming issues.

Calling WCF services from NetCF 3.5 using Compact WCF and NetCFSvcUtil.exe

The .NET Compact Framework 3.5 adds a subset of the Windows Communication Foundation (WCF or “Indigo”) to smart devices, allowing them to communicate with desktop WCF components with all the flexibility of multiple, interchangeable service bindings and endpoints.  Although it ships out of the box only with support for message-level communication (no service calls, per se), we have a code generation tool that will allow you to call WCF or other WSDL-publishing services.

Desktop has an svcutil.exe tool that generates client proxy code, but the source code it generates cannot compile against NetCF libraries because NetCF does not include all the classes referenced from that source code.  While you can modify the code by hand to eventually get it to work with NetCF, we offer an easier way.

The NetCFSvcUtil.exe tool that ships as part of the Power Toys for .NET Compact Framework 3.5 supports many of the same command-line switches that svcutil.exe does, but performs a few additional/modified steps:

  1. Verifies that the service being consumed offers endpoints compatible with the feature subset included in NetCF 3.5.
  2. Generates the client proxy class in C# or VB that compiles against NetCF or desktop WCF.
  3. Generates code for a CFClientBase class that fills in where NetCF doesn’t support calling WCF services.
  4. Does not generate a .config file to store the endpoint information.  This information is stored in the client proxy code.  If an X509 certificate required by the endpoint, that must be passed into the proxy class’ constructor by your code.

Assuming that you have a service running at http://localhost/service/service.svc on your desktop computer and a device application in your C:\deviceapp directory, you could generate the code to call the service from NetCF using the following command line.  Be sure NetCFSvcUtil.exe is in your path.  Also be sure to use a machine name that can be reached from your device.  If you use “http://localhost/…” as your argument to the tool, your device will look for localhost (which is the device itself!) and not find the service that is running on your Windows box.

C:\deviceapp>netcfsvcutil.exe http://<machinename>/service/service.svc

The tool will generate and list two source files.  The source file named after your service will be the one that contains the proxy class you’ll use from your app.  You can use it just like you would the svcutil.exe-generated code, except for the provision of secure endpoints made in my numbered list above.

To use these source files in your application, add them to your Visual Studio project and be sure you have System.ServiceModel.dll and System.Runtime.Serialization.dll in your project’s Referenced Assemblies list in Solution Explorer.  Calling your service from your device application can be as simple as a couple of lines of code:

CalculatorServiceClient client = new CalculatorServiceClient();
MessageBox.Show(client.Add(3, 5));

Some features that WSDLs and the desktop .NET WCF supports are not supported by the .NET Compact Framework 3.5.  Although NetCFSvcUtil.exe generates code to enable some of these features, here is a list of features that remain unavailable for our first version of Compact WCF when calling a WCF service on desktop:

  • Fault contracts (they are not automatically deserialized for you, but you get the raw xml that you can parse manually)
  • Custom message headers (including peer hop counts)
  • Callback contracts
  • Sessions
  • Mandatory transactions

And the only desktop binding NetCF 3.5 supports is basicHttpBinding, with optional WS-Security (X.509 only) and no support for WS-ReliableMessaging.  NetCF 3.5 adds the new mail transport as well, but NetCFSvcUtil does not support generating proxies for services exposed only on the mail transport.

It’s worthwhile to note that any service or client that supports WSDL contracts should be able to intercommunicate, regardless of underlying implementation.  This means that if you have a desktop WCF service that you want to call from NetCF, you may also use the already-existing Add Web Reference in Visual Studio to generate code for your client proxy class (the command line equivalent is wsdl.exe).  The resulting proxy class may not have as friendly of a public API for you to use, and it won’t use the WCF stack, but it is a valid alternative that will work in many cases.

The reverse is also true: you can use WCF to call into old-style .asmx web services.  It is not necessary to even know which web service implementation is used on a server.  So long as it publishes a WSDL, you’re in luck.  If it doesn’t publish a WSDL, you may still be able to generate a client proxy for it as long as it uses WCF service model and you have access to the managed service assemblies.  But that’s another topic.