WWSAPI to WCF interop 10: WsUtil.exe, the silver bullet

In my previous post on interoperating with WCF BasicHttpBinding endpoint, I explained that you had to set the channel properties to match SOAP version and addressing version on the server side. Wouldn’t it be great if you don’t have to do all that? That’s one of the goal of building WsUtil.exe, the silver bullet for interoperating with WCF (and any other web services stacks, as long as WSDL is available) by generating the matching proxy/stub files from the WSDL files. Now, as promised before, let’s see how WsUtil.exe can help you build the matching binding.

 

WsUtil.exe takes WSDL files and/or XSD files as input, so you first need to get the WSDLs from the service endpoint. SvcUtil.exe, a WCF tool also included Win7 SDK, can be used to get the WSDL/XSD files. For example, if your service endpoint is https://localhost/CalculatorService/ and the service also exposes a MEX endpoint or HTTP GET endpoint, you can run SvcUtil.exe /t:metadata https://localhost/CalculatorService/ to download the WSDL/XSD files. You can then generate the proxy/stub files using this command:

WsUtil.exe *.wsdl *.xsd

 

The files generated will look like: tempuri.org.wsdl.h and tempuri.org.wsdl.c. The .c file contains all the definitions of function stubs and serialization structures that are not easy to read, but the header file contains only declarations and lots of comments. The header files are meant for developers to read. Once you generate the files, open the header file for the WSDL file (e.g. the tempura.org.wsdl.h). The file starts with lots of comments explaining the contents and usage. Scrolling down, you will see two helper function prototypes like these:

 

HRESULT BasicHttpBinding_ICalculator_CreateServiceProxy(

    __in_opt WS_HTTP_BINDING_TEMPLATE* templateValue,

    __in_ecount_opt(proxyPropertyCount) const WS_PROXY_PROPERTY* proxyProperties,

    __in const ULONG proxyPropertyCount,

    __deref_out_opt WS_SERVICE_PROXY** _serviceProxy,

    __in_opt WS_ERROR* error);

struct BasicHttpBinding_ICalculatorFunctionTable;

HRESULT BasicHttpBinding_ICalculator_CreateServiceEndpoint(

    __in_opt WS_HTTP_BINDING_TEMPLATE* templateValue,

    __in_opt CONST WS_STRING* address,

    __in_opt struct WSHttpBinding_IChatFunctionTable* functionTable,

    __in_opt WS_SERVICE_SECURITY_CALLBACK authorizationCallback,

    __in_ecount_opt(endpointPropertyCount) WS_SERVICE_ENDPOINT_PROPERTY* endpointProperties,

    __in const ULONG endpointPropertyCount,

    __in WS_HEAP* heap,

    __deref_out_opt WS_SERVICE_ENDPOINT** serviceEndpoint,

    __in_opt WS_ERROR* error);

The first function prototype is for creating WS_SERVICE_PROXY on the client side and the second is for creating WS_SERVICE_HOST on the server side. We only need to use the client side helper function.

 

    hr = BasicHttpBinding_IChat_CreateServiceProxy(

            NULL,

            NULL,

           0,

            &serviceProxy,

            error);

 

As you can see, instead of setting the two channel properties and then call WsCreateServiceProxy as shown in my previous post, you just need to call the helper function once to create the service proxy. You can then call WsOpenServiceProxy to open it before making calls that are listed in the same header file just below the helper functions.

 

You can set more channel properties (like send/receive timeout) in WS_HTTP_BINDING_TEMPLATE. In this scenario we just pass NULL as the template value since we don’t need to define any more channel properties.

 

For more information on WsUtil.exe, please refer to this WSDN page: https://msdn.microsoft.com/en-us/library/dd430644(VS.85).aspx.