Monday, 21 January 2013

Interoperable WCF

Introduction

Web Services have been designed for interoperability, so you would expect that clients and servers created  using different tools interoperate smoothly. In reality it's far from being that simple. Multiple and evolving standards and features created the situation where no two systems are the same. It led to creation of Web Services Interoperability Organization with the purpose to establish best practices for interoperability for select group of standards. Further information can be found at http://www.ws-i.org

WS-I Basic Profile

As the name suggests,WS-I Basic Profile defines minimal set of standards a Web Service should support. Unfortunately, the Basic Profile specification has number of versions which are not necessarily interoperable. For example, system compliant with WS-I version 1.0 might not be able to interoperate with a system compliant with WS-I version 2.0.

Windows Communication Foundation supports WS-I with BasicHttpBinding which conforms to WS-I version 1.1. Basically, it means compliance with SOAP 1.1, WSDL 1.2 and UDDI 2.0. It is also understood that internet standards like XML Schema, SSL, X.509 etc are also supported.

Delphi client

Although Delphi introduced support for Web Services early, it doesn't have many advanced features and interoperability with Web Services created with other systems has always  been limited. It's getting better with every new version of Delphi, though. 

It's fairly easy to consume WCF service configured to use BasicHttpBinding. Let's use Interoperable Web Service Demo at http://aspspider.info/burzyn/echoservice.svc as an example. The WSDL document can be generated using the following link http://aspspider.info/burzyn/echoservice.svc?WSDL

To import the Echo Service into a Delphi project select File | New | Others | WebServices |  WSDL Importer and paste http://aspspider.info/burzyn/echoservice.svc?WSDL into the WSDL Source.
Also in Delphi XE2 or newer, there's a new option in the Components menu, which is an alternative way to import WSDL. Use Components | Import WSDL to create a unit to be shared by multiple projects.

WSDL document generated from WCF service usually contains two file, the main file and the second file referenced by using the following line.
<wsdl:import location="http://aspspider.info/Burzyn/EchoService.svc?wsdl=wsdl0"/>
Delphi older then 2009 will not be able to import it correctly, as it processes just the main file and information from this file alone might not be sufficient. This has been remedied in .NET Framework 4.5 by providing an option to generate WSDL document as a single file. Single file WSDl document is accesible at http://aspspider.info/burzyn/echoservice.svc?singleWSDL

Summary

This is just the beginning. Services based on BasicHttpBinding might not be sufficient for every requirement. Connecting to WCF services built using other bindings might be a bigger challenge, but it's not impossible. It might require significant SOAP expertise, though.


Thursday, 17 January 2013

Interoperable Web Service Demo

Common scenario

I've been involved in interfacing to WCF using other tools than Visual Studio (Delphi) more than once. Short discussion can be found at Interoprable WCF. I thought it would be a good idea to have a reference service available and this is how the idea of Echo Service was born. Echo Service illustrates typical issues associated with accessing web services - calling a method with parameters of simple and complex type, handling declared and undeclared exception, as well as downloading a large binary data.

The Implementation

The Interoperable Web Service Demo is currently hosted in http://aspspider.info/burzyn/echoservice.svc. Apart from BasicHttpBinding, it exposes WsHttpBinding and WebHttpBinding at http://aspspider.info/burzyn/echoservice.svc/ws and http://aspspider.info/burzyn/echoservice.svc/web respectively. WebHttpBinding can be accessed using the browser with the syntax like:
http://aspspider.info/burzyn/echoservice.svc/web/echostring?value=test1.

Here's the the 'service.model/ group from web.config:
  <system.serviceModel>
    <services>
      <service behaviorConfiguration="Metadata" name="Altaira.Demos.EchoService">
        <endpoint name="BindingInterop" address="" binding="basicHttpBinding" bindingConfiguration="" contract="Altaira.Demos.IEchoService"/>
        <endpoint name="BindingREST" address="web" binding="webHttpBinding" behaviorConfiguration="WebBehavior" contract="Altaira.Demos.IEchoService"/>
        <endpoint name="BindingStandard" address="ws" binding="wsHttpBinding" contract="Altaira.Demos.IEchoService"/>
        <host>
          <baseAddresses>
            <add baseAddress="'http://aspspider.info/burzyn/echoservice.svc"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name="WebBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="Metadata">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
  </system.serviceModel>
 Note that includeExceptionDetailinFaults is set to 'false'. It' intended for testing the scenario when an undeclared exception is raised on the server side, so that the CommunicationException is raised rather than  FaultException. You can test it calling UndeclaredFault() method.

Further information is available at request.