Auto-Generate SOAP Proxies from Web Service Projects

Generating WSDL from the Web Service Project

The first step is to automatically generate of any method is to be able to generate the wsdl directly from the project files without the need to publish them to a web service first.  While this seems like something that Microsoft should have right out of the box, it took some searching to come up with the CmdHelper application from Stephan Brenner.  This utility is able to generate the WSDL from a web service assembly, without the need to start a web server.

To use this utility, simply install a copy locally and run the command:

CmdHelper.exe GetWsdl /AssemblyPath:c:\myWebApp\bin\myWebApp.dll /OutputDirectory:c:\output

This generates the WSDL for all web services in the assembly.  Alternately there is a command line version to selective output specific instances.

Generating Proxies from the WSDL

Now that we have the WSDL file, we can generate the proxy class.  However, instead of using the Web References to generate the proxy and add it to our project, we need to use the wsdl.exe command line utility.  This is simply a matter of calling the command:

wsdl  /namespace:my.namepace Service.wsdl /out:proxy.cs

Generating Proxies for .NET CF

If the proxies are going to be used with .NET CF 2.0 and .NET CF 3.5, which has a reduced set of .NET functionality including some async methods used in the generated proxy.  To avoid these conflicts, you can build the proxy with the “oldAsync” method (using BeginMethod/EndMethod syntax which is supported.

To do this the wsdl.exe must be called with an XML parameters file to set the “oldAsync” properties as described in Creating a Web Service Proxy for a .Net 2.0 Web Service.  Additional details for configuring parameters are provided at the MSDN Web Services Description Language Tool (Wsdl.exe) and CodeGenerationOptions Enumeration pages.

My wsdl command line becomes:

%wsdl% /v /parameters:"%~dp0\oldwsdlconfig.xml"  /namespace:%NameSpace% %ProjectPath%\proxy\Service.wsdl /out:%ProjectPath%\proxy\%ProxyName%

and my parameter file, “oldwsdlconfig.xml” is:

<wsdlParameters xmlns='http://microsoft.com/webReference/'>
  <language>c#</language>
  <protocol>Soap</protocol>
  <nologo>true</nologo>
  <sharetypes>false</sharetypes>
  <webReferenceOptions>
    <codeGenerationOptions>properties oldAsync</codeGenerationOptions>
  </webReferenceOptions>
</wsdlParameters>

Automating the Process

Finally to automate the entire process is a matter of run a batch file as a post-build step in each of the web service projects.

The batch file I use is called GenProxy.bat:

if NOT "%~1" == "" goto start
echo "usage: GenProxy    "
goto end
 
:start
set wsdl="C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\wsdl"
set ProjectPath=%~1
set AssemblyPath=%2
set NameSpace=%3
set ProxyName=%4
set cmdhelper="%~dp0\..\Tools\CmdHelper\cmdhelper"
 
echo "Project Path: %ProjectPath%"
echo "Assembly Path: %AssemblyPath%"
echo "Name Space: %NameSpace%"
echo "Proxy Name: %ProxyName%"
echo "CmdHelper: %cmdhelper%"
 
cd %ProjectPath%
if NOT exist proxy mkdir proxy
%cmdhelper% GetWsdl /AssemblyPath:%AssemblyPath% /OutputDirectory:%ProjectPath%\proxy
%wsdl% /v /parameters:"%~dp0\oldwsdlconfig.xml"  /namespace:%NameSpace% %ProjectPath%\proxy\Service.wsdl /out:%ProjectPath%\proxy\%ProxyName%
 
:end

Which requires the helper oldwsdlconfig.xml file from above.

Then finally include running the GenProxy.bat command as a post-build step in the project:

call $(ProjectDir)..\..\..\Scripts\GenProxy.bat "$(ProjectDir)" $(TargetPath) my.namespace wsProxy.cs

Now the wsdl file and the associated proxy will be included in the proxy directory of the project and can now be used by other projects to access the web service.  For this I typically just add a link to the existing item.