<body><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener('load', function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <div id="navbar-iframe-container"></div> <script type="text/javascript" src="https://apis.google.com/js/platform.js"></script> <script type="text/javascript"> gapi.load("gapi.iframes:gapi.iframes.style.bubble", function() { if (gapi.iframes && gapi.iframes.getContext) { gapi.iframes.getContext().openChild({ url: 'https://www.blogger.com/navbar.g?targetBlogID\x3d17214516\x26blogName\x3dI+Can+Hack+It\x26publishMode\x3dPUBLISH_MODE_BLOGSPOT\x26navbarType\x3dBLUE\x26layoutType\x3dCLASSIC\x26searchRoot\x3dhttps://icanhackit.blogspot.com/search\x26blogLocale\x3den_US\x26v\x3d2\x26homepageUrl\x3dhttp://icanhackit.blogspot.com/\x26vt\x3d7576809980937220326', where: document.getElementById("navbar-iframe-container"), id: "navbar-iframe" }); } }); </script>
  Self-documenting .NET Web Services
Antiphonar
Image courtesy of
Visipix.com
I recently had to work with a Web Service provided by a vendor. I exchanged emails for a couple of weeks just to figure out how to make it work. It should not be so!

Developers are familiar with the reams of documentation that usually accompany an API or SDK. Help files integrated into development tools are of great help such as the MSDN integration into Visual Studio and Intellisense. However, when dealing with programmers that seem bent on keeping everyone else in the dark, no amount of Intellisense is going to be of any help. This is specially maddening as it applies to what is supposed to be the .NET holy grail of "...information anytime, anywhere, on any device."

The following should look familiar; It is a Web Service's .asmx page that .NET automatically generates along with the WSDL to be used by the Web Service consumer. The .asmx page is the deployment interface of a .NET Web Service. It provides a testing mechanism and lots of information if one is into parsing XML in one's head.

PartnerIntegration


PROCON Web Services for activation of retail Customers.

The following operations are supported. For a formal definition, please review the Service Description.

A major deficiency of the .asmx page is that the only sections available for the developer to document the Web Service seem to be one-liners extracted from the code, specifically the WebService and WebMethod descriptions attributes as in:

<System.Web.Services.WebService(Description:="PROCON Web Services for activation of retail Customers.", _
                                Namespace:="http://webservices.poweredbysat.com/PartnerIntegration")> _
Public Class PartnerIntegration
    Inherits System.Web.Services.WebService

...

<WebMethod(Description:="Credit check for retail Customers.")> _
Public Function CreditCheck(ByVal PartnerID As String, _

...

<WebMethod(Description:="Activation for retail Customers.")< _
Public Function CustomerActivation(ByVal PartnerID As String, _
                                
The term "self-documenting code" is computerese for either "I am too lazy to document my program!" or "I am such a great programmer that if you don't understand my code you should not be allowed to peruse it, let alone maintain it!" But a self-documenting Web Service makes perfect sense because there is no better way to document it than right there where the Web Service is being deployed!

So how can a .NET Web Service be documented given the meager resource provided by description attributes? Wouldn't it be neat if we could just include HTML in the description of our Web Service as some .NET Web Services resources seem to suggest? Unfortunately, HTML tags included into Web Services' description attributes will not be interpreted as HTML in the .asmx page but will instead be rendered as text! However, once we understand that the .asmx page is generated from a default template then there are many possibilities for documenting a Web Service. Before hacking the DefaultWsdlHelpGenerator.aspx template, here is the criteria that I wanted to follow for documenting Web Services:
  • Keep the consistent style of the .NET .asmx page and its testing and WSDL functionality.
  • Avoid any changes that would alter the definition of the WebService and its WebMethods such as extraneous variables or additional coding.
  • Separation of the HTML documentation from the WebService code and no need for recompilation or redeployment of the Web Service if changes are made to the HTML documentation.
  • Allow for the default operation of the .asmx page when needed so that it can always be tested and not be suspect because of the changes made to enhance self-documentation.
  • Since the information been documented will probably be best presented in some sort of tabular form, it would be nice to this painlessly (Unless one is an HTML table masochist!)

Once I customized the WSDL Help Generator template there were only very minor changes necessary to implement a self-documented Web Service. Following are the changes necessary to the WebService and WebMethod description attributes. It should be intuitive that the documentation is included in external HTML files named for the WebService and WebMethods.

<System.Web.Services.WebService(Description:="PartnerIntegration.htm", _
                                Namespace:="http://webservices.poweredbysat.com/PartnerIntegration")> _
Public Class PartnerIntegration
    Inherits System.Web.Services.WebService

...

<WebMethod(Description:="CreditCheck.htm")> _
Public Function CreditCheck(ByVal PartnerID As String, _

...

<WebMethod(Description:="CustomerActivation.htm")< _
Public Function CustomerActivation(ByVal PartnerID As String, _
                                

Following is an example of what is possible when documenting a Web Service through external HTML files included in the rendered .asmx page.

PartnerIntegration


Version 2.0 [Staging]

This WebService implements methods for PROCON Partners to integrate activation services for retail Customers. The CreditCheck WebMethod is used to obtain a Credit Check confirmation code (ConfirmCC) which will be necessary when performing the actual activation through the CustomerActivation WebMethod.

The following operations are supported. For a formal definition, please review the Service Description.


Clicking for a full description of the CreditCheck WebMethod will show the following:

PartnerIntegration


Click here for a complete list of operations.

CreditCheck

Credit Check for retail Customers.

Required Parameters   Max  Description

    PartnerID:        20   Integration Partner ID for WebMethod Authentication.
    PartnerPass:      20   Integration Partner password for WebMethod Authentication.
    Title:            10   Customer's title ('Mr.' or 'Mrs.')
    FirstName:        30   Customer's first name.
    MiddleName:       30   Customer's middle name (May be blank)
    LastName:         30   Customer's last name.
    Address:          50   Customer's address.
    Address2:         50   Customer's address line2 (May be blank)
    City:             30   Customer's city.
    State:            30   Customer's state. (Two letter postal code)
    Zip:               9   Customer's zip. (5-digit postal code. 9-digit postal code if known)
    PhoneHome:        20   Customer's home phone number. (10-digit phone number including area code)
    SSN:               9   Customer's Social Security Number (9-digit SSN)

Returned values            Description [CCReturn Class]
    ErrorCode:             0 = CreditCheck OK.  Non-zero value = CreditCheck failure. (See next section for Error list)
    ErrorDesc:             OK or description for CreditCheck failure.
    ConfirmCC:             Credit Check confirmation code. (8-digit number. 8th digit is a Modulo 10 Check Digit) 
                           Valid ConfirmCC must be submitted to CustomerActivation WebMethod


ErrorCode ErrorDesc 0 OK CC10000 Credit declined. Generalized result with no specific reason provided. CC20000 Credit Check could not be completed by Bureau. CC30000 Integration Partner could not be authenticated. CC31100 Parameter Title missing. CC31200 Parameter FirstName missing. CC31300 Parameter LastName missing. CC31400 Parameter Address missing. CC31500 Parameter City missing. CC31600 Parameter State missing or invalid. CC31700 Parameter Zip missing or invalid. CC32100 Parameter PhoneHome missing or invalid. CC33100 Parameter SSN missing or invalid. CC900XX ConfirmCCs_New SQL Stored procedure failure XX. CC99990 WebMethod implementation error (Actual error included).

Here is a link to the working self-documented Web Service. As previously discussed, this is possible because I have customized my WSDL Help Generator template which can be downloaded here (Save Target As... & remove ".txt" from the filename, since it is an .aspx page!) The customized WSDL Help Generator template should be placed in IIS Server's <Windows System Folder>\Microsoft.NET\Framework\<.NET Framework Version>\CONFIG directory. It will not overwrite the original DefaultWsdlHelpGenerator.aspx template. It that is not possible or desired, the customized template can simply be deployed in the same directory as the .NET Web Service. To override the default WSDL Help Generator template, the following will have to be included in the .NET Web Service's web.config <system.web> section:

<webServices> <wsdlHelpGenerator href="WsdlHelpGenerator.aspx"/> </webServices>

Notice that the description of the WebMethods is extended in their individual documentation/test pages but only a short paragraph is included on the top page. This allows for the top page to provide an overall description of the WebService and list all the WebMethods without including the extensive documentation that should be part of each individual WebMethod. This is accomplished by enclosing all the HTML that should be listed in the top page in <description> tags. For example, the following HTML is for the CreditCheck WebMethod which provides a short description for the top page and the full documentation for the individual page:

<description> Credit Check for retail Customers. </description> <br><br> <pre> <u>Required Parameters</u>   <u>Max</u>  <u>Description</u>     <i>PartnerID:</i>        20   Integration Partner ID for WebMethod Authentication.     <i>PartnerPass:</i>      20   Integration Partner password for WebMethod Authentication.     <i>Title:</i>            10   Customer's title ('Mr.' or 'Mrs.')     <i>FirstName:</i>        30   Customer's first name.     <i>MiddleName:</i>       30   Customer's middle name (May be blank)     <i>LastName:</i>         30   Customer's last name.     <i>Address:</i>          50   Customer's address.     <i>Address2:</i>         50   Customer's address line2 (May be blank)     <i>City:</i>             30   Customer's city.     <i>State:</i>            30   Customer's state. (Two letter postal code)     <i>Zip:</i>               9   Customer's zip. (5-digit postal code. 9-digit postal code if known)     <i>PhoneHome:</i>        20   Customer's home phone number. (10-digit phone number including area code)     <i>SSN:</i>               9   Customer's Social Security Number (9-digit SSN) </pre> ...

Additional Notes & Resources:
  • Notice the <pre> tag in the HTML above. It encloses "pre-formatted" text that will be rendered with its normal spaces and carriage returns without the need to build HTML tables for rendering tabular data with the added benefit that it automatically fits the style of the original .asmx page for detailed information. Following is the HTML documentation for the WebService: PartnerIntegration.htm and its WebMethods: CreditCheck.htm & CustomerActivation.htm (Save Target As...)


  • If an HTML file is not defined in the description attribute, then the text is treated and rendered normally which is the default behavior of the WSDL Help Generator template.


  • The customized WSDL Help Generator lists WebMethods in alphabetical order which is an improvement over the random order that is the default behavior. This is helpful when a WebService consists of several WebMethods.


  • I have decided to allow the HTTP GET/POST methods for testing my Web Service. There are several security vulnerabilities in allowing this functionality and it should probably be disabled in a Production environment. However, I feel that the testing capability should be provided, at least in a Staging server environment, so that the Web Service can be readily tested and debugged by a consumer. For instructions on how to enable/disable the HTTP GET/POST and testing capabilities and even how to disable the documentation functionality altogether, see this MSDN article.


  • If the HTPP GET/POST testing will not work, it is usually a result of a bug in the Web Service. This seems to be always true if the result of the test page is an "HTTP 500 Internal Server Error". Several resources mention Windows permissions as an issue but I have been able to test Web Services successfully in a IIS6 server without giving additional permissions to the Web Service's directory (ASP.NET for IIS5 & IIS_WPG for IIS6) Apparently, in .NET 1.0, permissions to the <Windows System Folder>\temp directory had to be set, since this directory is used by .NET for XML serialization/deserialization.


  • Debugging a .NET Web Service is a little more complicated than debugging an ASP.NET mainly because there is no visible user interface; See this MSDN resource for more information in debugging Web Services.


  • There are many ways to secure a Web Service. For production purposes, I always implement my Web Services over SSL. For .NET 2.0, it seems that the newly available WS-Security Protocol is the preferred methodology.


  • A known and reproducible bug in using a customized WSDL Help Generator is related to how the Web Service will be deployed. This problem will occur if the Web Service is not deployed under a website's root directory. I deploy my Web Services as a subdomain that is its own IIS website. The Web Service application is deployed as a subdirectory under a "\WebServices" directory and an IIS "Virtual Directory" under the subdomain. The Web Service URL is a little long but this scheme keeps things organized. Also, a simple HTML page can be created to catalog all the different Web Services that could be implemented as separate applications for whatever reasons.


  • Interested in seeing the changes to the customized WSDL Help Generator that make self-documentation for .NET Web Services possible, as described in this article? Take a look at the .aspx C# source code and search for "HACK"!


Labels: ,

Posted by Sri Alexander Valarino on 7/15/2006   

Comments


Post a Comment            Home