« June 2004 | Main | August 2004 »

July 2004

The Web services empire strikes back - WS-I BP Conformance

Part 1: The Web services empire strikes back - Introductory thoughts
Part 2: The Web services empire strikes back - Inner Workings
Part 3: The Web services empire strikes back - Web Services in Visual Studio 2005

Honestly, aren't Web services a lot about interoperability? Yes, absolutely. And it is essential to the success of Web services and any Web services platform vendor that the interoperability between various implementations can be guaranteed. The first steps in this realm were made with the so called SOAPBuilders Interop Lab that has been established primarily as a virtual lab for builders of SOAP stacks. But with the advent of WSDL and UDDI respectively interoperability testing became noticeably harder. There the Web Services Interoperability Organization (WS-I.org) has been founded. One of the goals of the WS-I is to work out common scenarios, do's and dont's for three areas of interest in Web services landscape: messages, descriptions, and registry data. The respective specifications for SOAP, WSDL, and UDDI literally leave to much space for interpretation - and this is a killer for successful interoperability.

These best practices have been assembles into a document called the Basic Profile 1.0 (BP 1.0). The BP 1.0 addresses issues that can arise with SOAP 1.1 messages, allowing for future compatibility with SOAP 1.2 messages, typically sent over an HTTP 1.1 transport. Further it discusses the Web Services Description Language (WSDL) 1.1 documents exposed by Web services, allowing for future compatibility with WSDL 1.2 definitions. Last but not least it talks about how to use registry data for discovery, such as UDDI tModels. The BP 1.0 is the de-facto standard document to follow when building on tomorrow's Web services interoperability. And Microsoft took a bunch of developers and integrated the BP 1.0 into ASMX v2 (Note: discovery data is outside the scope of the .NET Framework 2.0's Basic Profile 1.0 conformance support).

Every Web service you create in Visual Studio 2005 will be BP1.0 compliant by default. This is good and helps to further ensure and enable true interoperability if all other Web services runtime/engine vendors will do the same in their upcoming revisions of their products.
Here is an example of a classical 'Hello World' Web service in ASMX v2:

using System.Web.Services;
using System.Web.Services.Protocols;

[WebServiceBinding(
  ConformanceClaims=WsiClaims.BP10,
  EmitConformanceClaims=true)]
public class Service_asmx
{
  [WebMethod]
  public string HelloWorld()
  {
    return "Hello World";
  }
}

The most important fact to notice in the above code is the usage of the WebServiceBindingAttribute class. Not that this binding is all new, not at all. If you are leveraging multiple bindings in a Web service this attribute is already very familiar to you. It declares the binding one or more Web service methods implemented within the class. A binding is similar to an interface in that it defines a concrete set of operations. Each Web service method is an operation within a particular binding. And it is exactly this concept of a binding that the BP 1.0 conformance implementation of ASMX works on.
The ConformanceClaims parameter of WebServiceBindingAttribute shows which level of conformance to follow. Currently there are just two values in the WsiClaims enumeration to use: None and BP10. The value BP10 indicates to use the Basic Profile 1.0 conformance rules to follow. An additional step is to instruct the ASMX engine to emit conformance claims into the service description. By setting the EmitConformanceClaims property to true your Web service's WSDL will be enriched with BP 1.0 conformance claim information. A small sample for a WSDL snippet can be seen here:

<wsdl:binding name="foo" type="tns:foo">
  <wsdl:documentation>
    <wsi:Claim conformsTo="
http://ws-i.org/profiles/basic/1.0"
      xmlns:wsi="
http://ws-i.org/schemas/conformanceClaim/" />
  </wsdl:documentation>
  <soap:binding transport="
http://schemas.xmlsoap.org/soap/http"
    style="document" />
  <wsdl:operation name="HelloWorld">
    <soap:operation soapAction="
http://tempuri.org/HelloWorld"
      style="document" />
    <wsdl:input>
      <soap:body use="literal" />
    </wsdl:input>
    <wsdl:output>
      <soap:body use="literal" />
    </wsdl:output>
  </wsdl:operation>
</wsdl:binding>

This piece shows how the wsdl:documentation element is used to emit optional metadata about the conformance level of the regarding WSDL element (the binding in this case) into the automatically generated WSDL. It is important to notice that this is just for informational purposes. A WSDL processor does not need to understand this information and a Web services can be conformant without explicitly stating it through such claims in the WSDL.
If you try to use features in your Web service that are officially not supported by the BP 1.0 you will get a hint when you point to the service's help and test page. The help page shown in figure 4 is generated when we decorate our Web service from above with the SoapRpcService attribute. Obviously RPC/encoded Web services are discouraged by the WS-I and the help page actually tells us which statements of the BP 1.0 is violated. In this case it is R2706: A DESCRIPTION MUST use the value of 'literal' for the use attribute in the SOAP Binding description. Which means that you can either use RPC/literal or Document/literal style Web services. For those of you who do not like to see such warnings there is a configuration switch to disable this functionality.

Web services test page warnings
Figure 4: Web services test page warnings

On the other side, Web service clients based on .NET Framework 2.0 are also conformant by default - of course unless the WSDL which it is targeted at is non conformant. The wsdl.exe command line tool as well and the new incarnation of the 'Add Web Reference ...' dialog (not yet implemented in Beta 1) checks for WSDL conformance and gives you warnings if the WSDL is non conformant.

Here's an example message from wsdl.exe when consuming a WSDL document that uses SOAP encoding, which is prohibited by the BP 1.0 document:

Microsoft (R) Web Services Description Language Utility
[Microsoft (R) .NET Framework, Version 2.0.40325.0]
Copyright (C) Microsoft Corporation. All rights reserved.

Warning: This web reference does not conform to WS-I Basic Profile v1.0.
R2706: A DESCRIPTION MUST use the value of 'literal' for the use attribute
in the SOAP Binding description.
  - Operation 'HelloWorld' on binding 'EncodedServiceSoap' from namespace
'http://tempuri.org/'.
Writing file 'C:\Demos\EncodedService.cs'

The support for the Basic Profile 1.0 will further ensure interoperability with other Web services toolkits such as Apache Java Axis as soon as they support the conformance checks based on the BP 1.0. The Axis team over there is currently working on making 1.2 BP-compliant.

The Web services empire strikes back - Web Services in Visual Studio 2005


OK, enough theory so far. Let's start to get real. The first thing that has changed on a Web service's surface in .NET is how you actually program it. Of course, you can still do it all in Notepad, or Emacs if you are a famous person in town, and place the file in an appropriate location where ASP.NET can grab it. But here the differences between V1 and V2 begin. As already mentioned several times, ASMX sits on top of ASP.NET. And therefore it also leverages ASP.NET's compile and execution model.
 
In ASP.NET 2.0 there is no longer a need to compile your code and put it into the bin folder. As long as you are using the code-behind approach for development, it is sufficient to place your implementation file into a folder called 'Code'. The ASP.NET runtime will then take care of those files and compile them on the fly (don't worry, you still can pre-compile your applications and services).

Another point that has changed is how you start to develop a Web service in the IDE. Depending on the current scheme activated in Visual Studio 2005 you tell the IDE "File - New - Web Site …" and a new ASP.NET Web services project is born. Figure 3 shows you how the situation looks like after creating a plain new Web services project.
 
Bare Web services project in Visual Studio 2005
Figure 3: Bare Web services project in Visual Studio 2005 [BasicService_in_VS2005.jpg]

Well, 'project' isn't the right word here. At least, it is not a project as we know it from current Visual Studio .NET versions. There is no notion of a project file - it is all file based by default. Obviously you still can create an IIS-based new project, but the default uses a newly developed mini web server which has its origins in the Cassini project. We just have our .asmx and our .cs or .vb implementation files beneath the 'Code' folder - that's it.
Please note that I think that this very code as can be seen in the above picture is not what should be generated - please see my own opinion about how a 'Hello World' Web service should look like.

ASMX's 'HelloWorld' as it is supposed to be - VS team look!

[Update: I forgot an important attribute - which is responsible for Whidbey's BP 1.0 compliance]

Sorry, I have a request. These days, I am thinking a lot about contract-first design and development of Web services. If we cannot get a nice graphical contract editor, then we at least could try to model our .NET-based code to hammer down an actual contract and decouple the internal .NET implementation from this message and interface contract notation. You may want to call this 'code-based contract-first' versus 'schema-based contract-first'. Anyway ...

Hopefully the Visual Studio 2005 team will change the default code template for the still too simple and misleading Web Services wizard in Beta 1. And ... what about the coding style with curly braces at the end of the line? The current Beta of VS 2005 generates ugly code, IMO.

So here is my suggestion of what Visual Studio should actually generate - in order to propagate the message-based nature of Web services (all other VS-necessary code and comments stuff ommitted ...):

HelloService.asmx.cs:

[WebServiceBinding(ConformanceClaims=WsiClaims.BP10, EmitConformanceClaims=true)]
[WebService(Namespace="urn:thinktecture-com:demos:webservices:2004:v1")]
[SoapDocumentService(ParameterStyle=SoapParameterStyle.Bare)]
public class HelloService : System.Web.Services.WebService
{

   [WebMethod]
   [return: XmlElement(ElementName="HelloResponseMessage")]
   public HelloResp HelloWorld([XmlElement(ElementName="HelloRequestMessage")]HelloReq req)
   {
      HelloResp resp = new HelloResp();
      resp.Hello = "Hello again ...";

      return resp;
   }
}

Messages.cs:

[XmlType(TypeName="HelloRequest", Namespace="urn:thinktecture-com:demos:webservices:messages:v1")]
public class HelloReq
{
}

[XmlType(TypeName="HelloResponse", Namespace="urn:thinktecture-com:demos:webservices:messages:v1")]
public class HelloResp
{
   [XmlElement(ElementName="Hello")]
   public string Hello;
}

Hope this makes sense ... well, of course we could discuss whether it really has to be a classical 'Hello World' thingie at all ...

The Web services empire strikes back - Inner Workings

Part 1: The Web services empire strikes back - Introductory thoughts

Let's now take a look at how ASMX Web services work inside. An important point here is how and where our Web services live. Which is the responsible entity to execute, control and shutdown all actions related to Web services lifetime. This leads us to the notion of an application home, a host where our Web services get executed in. And this is the first new piece in ASMX v2.

'WebHost'
Think about a feature that all web applications (including usual web apps such as ASP.NET pages) and services have in common. If we abstract unnecessary details away, they both are communicating via messages (HTML vs. XML) and the applications usually get activated by messages. So a logical step into the right direction would be to rely on an activation model that relies itself on messages. This is where the new codename 'WebHost' model comes around. WebHost is a unified model for hosting Web applications and services. It is a joint project of the ASP.NET and Indigo teams. Additionally, IIS is providing the operating system infrastructure to activate, monitor and manage worker processes within which ASP.NET applications and Web services and Indigo services run. Future version of WebHost will be able to receive messages on other protocols than the standard HTTP. But the first release will run hand in hand with IIS 5.x and IIS 6 and will therefore just support HTTP. As you can see in Figure 1, WebHost sits right behind the ISAPI DLL in IIS that implements the redirection of ASP.NET related HTTP messages to the actual ASP.NET runtime. This runtime either is hosted in the aspnet_wp.exe process for IIS 5.x or in a separate w3wp.exe worker process in the case of IIS 6. WebHost delivers a so called message dispatcher functionality that is able to dispatch the message to the correct message processor. In our case this is the ASP.NET HTTP runtime, but in future this can be Indigo or any other 'runtime' that plugs into this architecture.

Basic WebHost architecture overview
Figure 1: Basic 'WebHost' architecture overview


WebHost is an ongoing project. Bits and pieces of its functionality will be released with every major release to come. So some bits of it will come with the upcoming Whidbey version, other bits with Longhorn.

Pipeline Architecture
Once a message has gone through WebHost's message dispatcher it will arrive at the HTTP runtime. The ASP.NET runtime consists of a pipeline that has several Http handlers that ultimately handle the message they were designed and implemented for. An example are SOAP messages that get transported to an implementation located in a .asmx file. The responsible HTTP handler is registered in the machine.config file and knows how to handle SOAP messages and how to send SOAP messages back. This is the actual heart of ASMX. Figure 2 depicts this situation while also showing a bunch of HTTP modules that can get in to the way of a SOAP message over HTTP until it receives its final destination, the .asmx endpoint.

ASP.NET pipeline with HttpHandler for handling Web services requests
Figure 2: ASP.NET pipeline with HttpHandler for handling Web services requests


HTTP handlers can process a HTTP packet transparently for the HTTP handler and are available for any handler configured in the HTTP pipeline. Typical scenarios are the handling of authentication or session management on HTTP level. On the other side, SoapExtensions are an extensibility mechanism for the ASMX engine. With the help of a SoapExtension you can work with the raw SOAP message in any way you want. E.g., a SoapExtension can be used to de- and encrypt messages, to compress and decompress SOAP Envelopes or just to take the message stream and log it to a file or database. The possibilities are open to your fantasy and potential.
So to sum up, once a SOAP message, delivered via HTTP and traveling through the ASP.NET pipeline, reaches the final .asmx endpoint implementation, the ASMX engine can handle all the necessary XML to object and vice versa processing in order to provide the powerful features mentioned in the first part of this series.

About XML

From a customer during a consulting gig last week where we talked about the pros and cons of XML, Web services and SOA:
   "The problem of XML is not just that it is human-readable, but that it is also manager-readable ..."

Enough said.