in

ASP.NET Weblogs

Yves Reynhout's Blog

The seagile man

June 2004 - Posts

  • WSE 2.0 Extensibility: From spec to code

    I've started work on a WS-ReliableMessaging implementation over at Plumbwork.Orange. Although I haven't made any serious advances (usability wise), it already shows that WSE 2.0 extensibility model is awesome! If you plan on writing an implementation of a spec yourself on top of WSE 2.0, dig in using Reflector or fetch a fresh copy of the Plumbwork.Orange source.

    So, how's the code organized? You have a WS<spec>.cs containing all the string identifiers (namespace, actions, element names and attribute names) relating to the spec. This class has a real "add code as we go" feeling to it. Next up are the elements and their associated attributes described in the spec. Basically you need to provide an object model, and write the serialization & deserialization code for each element. The namespace in Microsoft.Web.Services2.Xml will provide usefull services in this area. Carefully examine the spec to see if you need to derive from OpenElement (allowing any (elements) and @any (attributes)) or OpenElementElement (allowing only any (elements)). The structure of these element classes smells like what xsd.exe /c would generate for you (instead of attributes, think deriviation and add the implementation of an IXmlSerializable look-a-like). If the spec exposes service methods, then add a <spec>Service class (as you would implement a regular webservice using WSE 2.0) and provide the implementation for those methods using the element classes you've created. If the spec requires the use of custom headers, derive from SoapInputFilter and SoapOutputFilter (found in Microsoft.Web.Services2) and handle the headers (again) using the element classes.

    In a follow-up post I'll discuss where soap faults and policies go...

    Posted Jun 28 2004, 12:03 AM by yreynhout with 1 comment(s)
    Filed under: ,
  • From the trenches: WseWsdl2.exe

    This post has been deprecated by WSE 2.0 SP1 (they've added the "name" commandline parameter to wsewsdl2.exe).

    "This WSDL to SoapClient tool generates proxy code for Web service clients from WSDL files."

    The documentation states you can retrieve the WSDL via soap.tcp:
    "Soap.tcp locations will be retrieved with a SOAP message ("GetDescription")."

    Well, the documentation is not correct. First of all its not GetDescription but RequestDescription. Second, you need to inherit from SoapService in order to get the RequestDescription out-of-the-box. The GetDescription method exists in the SoapReceiver class and by default returns null.  So if you happen to inherit from SoapReceiver(which BTW SoapService inherits from), you can provide an implementation for SoapReceiver.GetDescription. But this buys you nothing. You need to provide a method with a SoapMethodAttribute which has a value of SoapReceiver.RequestDescriptionAction (== "http://schemas.microsoft.com/wse/2003/06/RequestDescription").

    Nevertheless, I did not get it to work properly (the proxy generation using soap.tcp that is). I kept on getting "Microsoft.Web.Services2.Addressing.AddressingFault: Destination Unreachable". On the net I found one other place where this was mentioned, but no reply. The funny thing is, that if I requested the description using a self-fabricated class inheriting from SoapClient and defined the RequestDescription method using the proper SoapMethod attribute, I got the WSDL back. So I started digging a little using Reflector and came to the conclusion that there was only one main difference between WseWsdl2 and my custom implementation. I used an EndPointReference with both an Address and a Via to initialize SoapClient, whereas WseWsdl2 used the constructor of EndPointReference specifying only the Address. So I changed my code to use the same constructor, and low and behold, I got the same error.  If address (specified on the SoapService itself via the SoapActor attribute) and via are the same, WseWsdl2 should work over soap.tcp!

    I whipped up a little tool to call the soap.tcp RequestDescription method using the proper EndPointReference constructor.
    Usage: soaptcpwsdl /address:<uri> /via:<uri> /output:<wsdl file>
    You can use WseWsdl2 on the wsdl output to generate the proxy class.

    UPDATE: Seems like I'm not the only one experimenting [http://weblogs.asp.net/gsusx/archive/2004/06/08/151351.aspx]
    UPDATE: Aaron Skonnard points out the use of WseWsdl2 [http://www.pluralsight.com/aaron/default.aspx?key=2004-06-04T21:48:22Z]

    Posted Jun 04 2004, 01:15 AM by yreynhout with 1 comment(s)
    Filed under:
  • WSE 2.0 Guts

    For the last couple of days I have been stairing at the inner workings of WSE 2.0 (using that well known tool) and I must say it's a fine piece of craftmanship. My focus has been on the Microsoft.Web.Services2.Messaging namespace, which provides the infrastructure (at long last) to host a soap server in your own application (without reverting to ASP.NET runtime hosting). It takes a while to wrap your head around the workflow because I've never seen that many asynchronous methods used together. It is a good example of how to use delegates, asynccallbacks, waithandles, ... to provide a scalable messaging solution.

    WaitHandleAsyncResult (found in Microsoft.Web.Services2) was a new concept to me. Basically an IAsyncResult implementation that doesn't fire an AsyncCallback until a WaitHandle is signalled. Very powerfull for multi-threaded communication and it's public(better rebuild it yourself in case they pull it from WSE 3.0). Too bad these kind of patterns don't get more attention. Another nice example (although hidden from the public eye) is Microsoft.Web.Services2.Messaging.SoapClient+SoapClientAsyncResult which shows you how to asynchronously send a soap request and on send completion, sit around and wait for the response to get back (again, asynchronously).

    When building your own transport, beware to derive your custom Soap<transport>InputChannel from SoapInputChannel, unless you plan to rewrite SoapTransport.DispatchMessage. An interface-based contract would have done the trick here, but I must agree that it probably would have confused the custom transport developer. SoapInputChannel internally uses a System.Collections.Queue to buffer messages and SoapTransport.DispatchMessage puts them into the buffer. Also note that you can't configure your custom transport (and thus scheme) using the configuration file. You must do this in code (or write your own config section handler which does the lifting)For some reason, the folks implementing the SoapTcpTransport where not happy using the Begin/EndAccept members of a socket, and implemented a windows socket event sink. They must have had their reason for doing this ... wonder what it could be.

    All in all a nice release ... one we can learn from.

    UPDATE: Steve Main shows us how to configure your custom transport (scheme) using the configuration file [Permalink]

    UPDATE II: After doing some more digging (actually stairing at same code over and over again) I finally found what I had been misinterpreting. If you specify a type attribute on the <messaging><transports><add> tag, another branch of the code is executed which does the transport type loading.

    So to conclude,

    <messaging>
        <transports>
            <add scheme="[Out-of-the-box transport scheme]"/>
        </transports>
    </messaging>

    or

    <messaging>
        <transports>
            <add scheme="[Custom transport scheme]" type="[Custom transport type]"/>
        </transports>
    </messaging>

    Posted Jun 02 2004, 01:25 AM by yreynhout with 4 comment(s)
    Filed under:
More Posts