Saturday, March 3, 2012

Consuming SOAP Web Services in Windows 8 HTML5 Applications

Windows 8 brings a great opportunity to use HTML and JavaScript to build rich desktop applications. I am coming from the managed world and used to some productivity features. One of these features is the Add Service Reference dialog and proxy generators for Web Services.

Interacting with SOAP web services involves a lot of overhead in creating envelop and formatting the message. This complexity is usually hidden behind proxies generated through the rich WSDL meta-information.

Unfortunately JavaScript has poor tooling support for interacting with SOAP services implemented with WCF or any other technology. The best approach when interacting with backend in JavaScript is to use REST based services that follows the simple HTTP protocol rules and returns JSON or XML formatted messages. But this option is not always available to developers.

Fortunately for Windows 8 developers the ability to implement WinRT components in managed languages and expose them to WinJS based applications. In this post the technique to expose a proxy for SOAP web services to HTML5 applications.

First add a new class library project to your HTML5 solution

Make sure that the output of this class library is WinMD file

Now use the Add Service Reference dialog to generate the proxy for the Web Service. The important trick here is to make sure that the proxy class are marked as Internal. WinRT exposed classes must follow some rules including being Sealed classes and expose WinRT compatible types. The proxy generated by the Add Service Reference dialog does not follow these rules, therefore the proxy should be internal or you will receive compiler error.

You will notice that all the generated methods are Async operations. This is to follow Windows 8 rules of responsive UI. The new C# and VB language features facilitate the usage of async operation. Async methods requires the return type to be either void or System.Task<T>. But System.Task is not a supported WinRT type and if you exposed an async method that returns data as a public method you will get a compiler error

“Error    3    Method has a parameter of type 'System.Threading.Tasks.Task' in its signature.  Instead of using a managed Task type, consider using Windows.Foundation.IAsyncAction, Windows.Foundation.IAsyncOperation, or one of the other Windows Runtime async interfaces.  The standard .NET awaiter pattern also applies when consuming Windows Runtime async interfaces.  Please see System.Runtime.InteropServices.WindowsRuntime.AsyncInfoFactory for more information on converting managed task objects to Windows Runtime async interfaces.   “

To work around this limitation wrap your async operation in a private or internal method and declare a public method that returns Windows.Foundation.IAsyncOperation<T> that wraps the async operation. The following code shows this technique in consuming the public Web Service for 2010 Soccer World Cup located at

   1:  public static Windows.Foundation.IAsyncOperation<TeamsData> GetData()
   2:  {
   3:      return getTeams().AsAsyncOperation();
   4:  }
   6:  internal static async Task<TeamsData> getTeams()
   7:  {
   8:      return await Task.Run(async () =>
   9:      {
  10:          var client = new InfoSoapTypeClient();
  11:          var result = await client.TeamsAsync();
  13:          var items = from i in result.Body.TeamsResult select i.sName;
  14:          return new TeamsData { Names = items.ToArray() };
  15:      });
  16:  }

Now in your HTML5 application you can add a reference to the managed project and use JavaScript futures to invoke the async operation as shown in the following code

   1:  var proxy = Backend.ServiceProxy;
   2:  proxy.getData().then(function (result) {
   3:      //do something
   4:  });

You can download the sample code here


Ibraheem Osama Mohamed said...

Great post :) and a very nice idea to consume the web service

Anonymous said...

Really good post.Great for people who are new to WIndows 8 HTML5 applications

Anonymous said...

Very Helpful