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.

 

 

ASP.NET Performance Monitoring

Recently we had a performance problem that caused poor response time, in the 10-15 seconds.  We are printing to handheld printers as one of the services which results in a long-running method, but should be able to handle the load we are seeing.

In order to understand the problem we did some performance monitoring to diagnose the problem.  These are the performance metrics that we used for monitoring performance.

Processor Performance (Processor):

  • % Processor Time – The percentage of elapsed time that the processor spends to execute a non-Idle thread.

Memory UsagePerformance (Memory):

  • % Committed Bytes In Use – The ratio of Memory\\Committed Bytes to the Memory\\Commit Limit. Committed memory is the physical memory in use for which space has been reserved in the paging file should it need to be written to disk.
  • Page Faults/sec – Page Faults/sec is the average number of pages faulted per second.

Network Performance (Network Interface):

  • Bytes Received/sec – The rate at which bytes are received over each network adapter, including framing characters.
  • Bytes Sent/sec – The rate at which bytes are sent over each network adapter, including framing characters.
  • Bytes Total/sec – The rate at which bytes are sent and received over each network adapter, including framing characters.

ASP.NET

  • Requests Current – The current number of requests, including those that are queued, currently executing, or waiting to be written to the client.
  • Request Execution Time – The number of milliseconds that it took to execute the most recent request.
  • Requests Queued – The number of requests waiting to be processed.
  • Request Wait Time – The number of milliseconds the most recent request was waiting in the queue.
  • Requests Disconnected – The number of requests disconnected due to communication errors or user terminated.
  • Requests Rejected – The number of requests rejected because the request queue was full.

ASP.Net Applications

  • Pipeline Instance Count – The number of active request pipeline instances for the specified ASP.NET application. Since only one execution thread can run within a pipeline instance, this number gives the maximum number of concurrent requests that are being processed for a given application. In most circumstances it is better for this number to be low when under load, which signifies that the CPU is well utilized.

Web Services

  • Current Connections – Current Connections is the current number of connections established with the Web service.
  • Total Method Requests/sec – The rate HTTP requests are received.
  • Bytes Total/sec – Bytes Total/sec is the sum of Bytes Sent/sec and Bytes Received/sec.  This is the total rate of bytes transferred by the Web service.

References:

ASP.Net MVC Modular Component Architecture

I have started adding a little bit more structure to our ASP.Net MVC project to start separating out the various components.  We needed to do this to create a framework that allowed multiple people to work on the application and modularize the code to make it more maintainable.

The basic architecture is to separate the various components in the web application in to the HTML and JavaScript components to reduce the coupling between them.   The HTML is moved in to Partial Views, similar to controls under Web Forms, and the JavaScript is separated in to a namespace hierarchy with separate modules for each of the components.

Partial Views

Separate the various components of the website in to partial views to allow them to be designed independently, shared between views, and to simplify the layout of the page.  This is very similar to how controls work in WebForms.

To do this, create a virtual page:

  1. Select the view directory to place the partial view, “Common” for those shared between different controllers, or in the View folder related to the controller, and select “Add->View”.
  2. Give the view a name, select “Create a partial view (.ascx)”, and “Add” the partial view.
  3. Copy the HTML layout in to the partial view.
    <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
    <div id="TimedPopup" class="popup hide">
      <div class="popupHeader">
        <div class="popupTitle">Message</div>
      </div>
      <div class="TimedMessageStyle">
        <div id="TimedMessageText"></div>
      </div>
    </div>
  4. Insert the Partial View in to the Views where it is needed.
       <% Html.RenderPartial("TimedPopup"); %>

Create the Namespace

Namespaces can be used to separate the code in to different separate blocks to avoid naming conflicts.

The namespaces that I we are using for our project is:

  • S1S: Root namespace for all code
  • UI: User interface code
  • <component>: The individual component code
  1. Define the namespace
    For this component the namespace will be “S1S.UI.TimedPopup”
  2. Add the component to the directory tree
    The scripts directory is segmented in to a hierarchy that maps to the namespace.  Add the component under the appropriate directory.  In this case add “TimedPopup.js” to “~/Scripts/S1S/UI”.
  3. Add the namespace setup to the javascript file
    Create the appropriate variables, being careful not to destroy previous objects.

    if (typeof S1S == "undefined" || !S1S) {
    S1S = {};
    }
    if (typeof S1S.UI == "undefined" || !S1S.UI) {
    S1S.UI = {};
    }

 Create the Component Module

  1. Now create a module for the actual logic for the component.  Use a basic module based on the following format:
    S1S.UI.TimedPopup = (function() {
     
      // Private Stuff Here
     
      return {
        // Public Stuff Here 
        Display: function(message) {
        }
      }
    } ());
  2. Implement the component functionality
    Finally implement the component functionality encapsulating the functionality in the module.  For instance you could have a private event handler:

    S1S.UI.Error = (function() {
      /* Close the Popup */
      var onOK = function() {
        $('#ErrorMessage').hide();
        $('#blanket').hide();
      };
     
      return {
        /* Display the Popup */
        Display: function(errorText) {
          // stuff
          $('#OK').one("click", onOK);
          }
        }
    } ());
  3. Use the Component
    To use the component, first add the JavaScript file to the view:

    <script src="<%= Url.Content("~/Scripts/S1S/UI/TimedPopup.js") %>" type="text/javascript"></script>

    and call the method as required:

    S1S.UI.TimedPopup.Display("Item successfully added!");