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.

 

 

VS 2005 SQL CE / xmta Error

Here’s another in the world of strange VS.NET 2005 error messages.  I have a project that I added some SQL CE code to and I get this message:

genasm.exe(1) : error There was an error finalizing type . Type ‘System.Data.SqlServerCe.SqlCeException, System.Data.SqlServerCe, Version=3.0.3600.0, Culture=neutral, PublicKeyToken=3be235df1c8d2ad3, Retargetable=Yes’ was loaded in the ReflectionOnly context but the AssemblyBuilder was not created as AssemblyBuilderAccess.ReflectionOnly.

After a little searching I found a couple of articles that describe the same problem.

The second one describes a long workaround from Microsoft to get around the problem, and the other has lots more.  But the both include the magic trick of changing the Build Action for xmta files to Content.  Which is all it takes to get around this crazy problem.
Updated Info:

I now have run in to another version of this same problem.  I have a Windows Form that contains a protected method containing a generic List as an out parameter.


protected virtual ResponseBase GetItems(out List<ItemVO> lstItems)
{
lstItems = new List<ItemVO>();
return ResponseBase.SuccessResponse;
}

I receive the error if the method is public or protected, but not private and the parameter is a ref or out. My solution was to change it to return an array of ItemVOs instead.  This is actually the scenerio described in the first article.

VS.NET 2005: “GenerateResource” task failed unexpectedly

Here is another reason why generated code drives me absolutely insane. It’s the mysterious errors that it invariably generates. In this case it is the error:

The “GenerateResource” task failed unexpectedly.

System.NullReferenceException: Object reference not set to an instance of an object.

at Microsoft.Build.Shared.ExceptionHandling.RethrowUnlessFileIO(Exception e)

at Microsoft.Build.Tasks.GenerateResource.NeedSeparateAppDomain()

at Microsoft.Build.Tasks.GenerateResource.Execute()

at Microsoft.Build.BuildEngine.TaskEngine.ExecuteTask(ExecutionMode howToExecuteTask, Hashtable projectItemsAvailableToTask, BuildPropertyGroup projectPropertiesAvailableToTask, Boolean& taskClassWasFound)

 

For no appraent reason I started to get this type of error in three of my SmartDevice projects in the same solution. Well the equally miraculous solution from http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=491745&SiteID=1 is to put the command:

 

 

<GenerateResourceNeverLockTypeAssemblies>true</GenerateResourceNeverLockTypeAssemblies>

 

in the project file in the PropertyGroup. And magically everything compiles and runs.

It’s things like this that really make me wonder if drag-and-drop designer tools have really helped us to write better code, or just allow us to get in to trouble in new and exciting ways.

SQL Mobile 2005 – Editing Table Data

In SQL Server CE 2.0 it was always painful to create the mobile database, and populate the data. However, with SQL Mobile 2005 and VS.NET 2005 Microsoft has come a long way to making the SQL Mobile database much easier to manage. While creating a new database is pretty well document, editing the table records is more obscure.

While developing the database is handled easily in the Microsoft SQL Server Management Studio, editing the database records requires VS.NET 2005. The “trick” to editing the database table is to use the Server Explorer (View->Server Exploer) in VS.NET to open the table for editing.

The first set is to add a Data Connection to add your mobile database to the project. This can be done by selecting the Data Connections option in the Server Explorer and choosing on the “Add Connection…” option in the pop-up menu. This will launch the “Add Connection dialog which you can use to specify the location and password of the database. For this example I am using the NorthWinds.sdf mobile database.

Add Connection - Northwinds

Once the Data Connection is successfully added you can now use the Server Explorer window to examine the various properties of the database. In order to open a table to edit, you must first expand the Table tree to see a list of all of the tables that are in the current database.

Server Explorer - Northwinds Database

Finally by selecting the table and choosing “Open” for the pop-up menu (right mouse) you can open the table and start editing. In this case I chose the customer database table.

Edit the Customer Table

SQL Mobile 2005 – Error: Not Enough Storage is Available

Here’s another in a long list of cryptic error messages. In this case I am developing a local database component for our SNAPRetail applications and on opening the database for the first time I get a SQLCEException with the message “Not enough storage is available to complete this operation”. Initially, I thought it was a problem with my database, but it is after a little searching I found a post (http://forums.microsoft.com/TechNet/ShowPost.aspx?PostID=895861&SiteID=17) on the Microsoft Technet forums that describes the problem as a “DLL Squeeze” and to open the connection to the database at the start of the appliation.

A little more research reveals that the DLLS that are being loaded are sqlceqp30.dll, sqlcese30.dll, sqlceer30en.dll, sqlceme30.dll which are the minium required for SQL Mobile to run.

VS.NET 2005 – Cannot create device project

I’ve been doing a lot of development in VS.NET 2005 for our SNAP projects, and decided to go back and do some work in VS.NET 2003 when I got the “helpful” message; “Cannot create device project. An installed SDK contains entries that duplicate existing entries and has corrupted the data needed for device connection. Uninstall the SDK.” As displayed below.

Cannot create device project warning

There is a similar message “Unable to read the project file ‘PInvokeVB.dbdproj’. And installed SDK contains entries that duplicate existing entries and has corrupted the data needed for device connection. Un-install the SDK.” Or whatever project you decide to open.

Unable to read project file Warning

These messages happened any time I opened or created a new Smart Device project.

Since Microsoft was not helpful enough to tell me which SDK is the problem, the search was on to figure it out. However, after un-installing essentially everything, i.e. SNAP, OpenNetCF Smart Device Framework, Intermec IDL, Symbol SMDK, and VS.NET 2003 itself, all that was obvious is that it had something to do with the Symbol SMDK 1.4 installation.

So it was time to break out the Sysinternals programs File Monitor (filemon.exe) and Registry Monitor (regmon.exe), two very useful tools. Fortunately, this pointed rather quickly to some old SMDK 1.1 files that were somehow left around in the devices addon directory (C:Documents and SettingsAll UsersApplication DataMicrosoftvisualstudiodevicesaddons).

Since there was both a “Symbol.SMDK.1.1.xsl” and “Symbol.SMDK.1.4.xsl” files, when the Smart Device projects are opened two sets of Symbol dlls are loaded, thus creating the duplicates. Simply delete the old SMDK 1.1 files and everything works correctly.