Wednesday, June 14, 2006

Atlas ASP.NET - using external web services


The sample created with Atlas April 2006 CTP, so the example might be obsolete someday. And remember - it's just one from several different ways to achieve the same results.
"Atlas" allows to access external web services, but it took for me a while to create a working application. And I decided to write a walkthrough for it. The purpose of the walkthrough is to show how to access the web service with less code as possible, so - no error checking. As a test web service I choose GeoIPService - it detects country by IP address.
You can download sources for the walkthrough here (6 KB). The archive doesn't contain Atlas dll, so you should add it yourself to the Bin directory.


Preparation

In Visual Studio 2005 create a new web site using Atlas web site template:

New project with Atlas Website template

From the created project delete unnecessary stuff (readme.txt, etc).

Server-side modifications


To access an external web service: a web application is accessing its home server, and the home server is accessing the external web service. That process named bridging. So let's create a bridge first.

  1. Generate server-side code for web service calls:

    1. Add App_Code ASP.NET folder (right-click on the project in Solution Explorer, Add ASP.NET folder \ App_Code).
    2. Launch VS2005 Command Prompt.
    3. In the console go to App_Code folder.
    4. Execute "wsdl.exe http://www.webservicex.net/geoipservice.asmx?WSDL".
      It will generated a strongly-typed proxy for the web service.
      Console with wsdl.exe

    5. Add generated class (GeoIPService.cs) to the project under the App_Code folder.


  2. Add a wrapper for the generated code. The wrapper class is simple - it creates an instance of the generated GeoIPService class, and perform a call to its method:
    public class GeoIPWrapper
    {
     public GeoIP LookupIP(string ip)
     {
     GeoIPService service = new GeoIPService();

     GeoIP geoIP = service.GetGeoIP(ip);
     return geoIP;
     }
    }
  3. The wrapper is not accessible directly from javascript code. To access it a bridge should be declared. So create xml file, and save it to the root of the project as GeoService.asbx. Content of the file should be:
    <?xml version="1.0" encoding="utf-8" ?>
     <bridge namespace="AtlasTests" className="GeoService" >
     <proxy type="GeoIPWrapper, App_Code" />
      <method name="LookupIP">
      <input>
       <parameter name="ip" />
      </input>
      </method>
     </bridge>

Client-side modifications


Open Default.aspx, and switch to Source view.
All changes will be done in this file, but I tried to separate changes logically.

Changes in HTML part
  1. Add a reference to the web service bridge in the ScriptManager definition.
    <atlas:ScriptManager ID="_scriptManager" runat="server">
     <Services>
      <atlas:ServiceReference Path="~/GeoService.asbx" />
     </Services>
    </atlas:ScriptManager>
  2. Add an edit box to enter an IP address.
    <input type="text" id="_boxIP" />
  3. Add Lookup button to initiate a call to the web service from the client-side. In onclick handler add a call to JavaScript function (the function will be defined soon).
    <input type="submit" id="_btnLookup" onclick="LookupIP(); return false;" />
  4. Add an empty DIV block for results.
    <div id="_results"></div>

Changes in JavaScript part

  1. Add a script section.
  2. Define variables for the edit box and results placeholder:
    var _boxIP = new Sys.UI.TextBox($("_boxIP"));
    var _placeholder = new Sys.UI.Label($("_results"));

  3. Implement LookupIP() function, it will make a call to the bridge. It's asynchronous call, so most parameters are callbacks.
    First parameter is a dictionary with <key, value> pairs - in our case it contains only one pair. Second parameter is a callback to receive results. Third parameter - a callback which will be called on timeout. Fourth parameter - a callback for errors. There are other parameters (onMethodAborted, userContext, timeoutInterval, priority, useGetMethod), but they are ignored in this walkthrough.
    function LookupIP()
    {
     var ip = _boxIP.get_text();
     AtlasTests.GeoService.LookupIP({'ip': ip}, OnGeoResults, OnTimeout, OnError);
    }
  4. Main callback is OnGeoResults() function. It receives an object with structure that is mirroring the structure returned by the web service.
    function OnGeoResults(results)
    {
     // if succeeded
     if (results.ReturnCode == 1)
     {
      var strResult = "IP: " + results.IP + "<br/>Country: " + results.CountryName;
      _placeholder.set_text(strResult);
     }
     else
     {
      _placeholder.set_text(results.ReturnCodeDetails);
     }
    }

    Two other callbacks are just stubs to notify us about critical situations.
    function OnTimeout(result, context)
    {
     alert("Timeout! " + result.get_message());
    }

    function OnError(result, response, context)
    {
     alert("Error! " + result.get_message());
    }

Tests


Now we have a web application which can call external web services. The application is simple, so tests are simple as well. :)
  1. Start the web application.
  2. Enter some valid IP address (remember, there are no error checking).
  3. And hit Lookup button.
  4. If everything is OK you should get information about the IP address:

    Results of lookup of IP address



Labels: , , ,