.NET Web Services I...

In this article we'll quickly review the basics of Web Services before continuing on in subsequent articles to look at Web Services in more depth.


By: John Kilgo Date: August 14, 2003 Download the code.

Introduction

Microsoft promoted Web Services a great deal with the launch of .NET. This seems to have faded a little with Web Services perhaps not having taken off as much as was thought. The concept of interoperability over the Internet is still a great one however. In this article we'll quickly review the basics of Web Services before continuing on in subsequent articles to look at Web Services in more depth. The current plan is to consider the following topics as follows:

Article 1:
Introduction: Overview, SOAP, DISCO, UDDI and WSDL; creating and consuming a WebService in VS.NET.

Article 2:
Customising the WebMethod attribute
Disco and UDDI practicalities
The disco.exe and wsdl.exe tools

Article 3:
Creating and using SOAP extensions
Creating asynchronous web methods
Controlling XML wire format

Hopefully I'll be able to squeeze all that into three articles!

First, to the basics.

What are Web Services?

Web Services enable the exchange of data and the remote invocation of application logic using XML messaging to move data through firewalls and between heterogeneous systems. Although remote access of data and application logic is not a new concept, doing so in such a loosely coupled fashion is. The only assumption between the Web Service client and the Web Service itself is that recipients will understand the messages they receive. As a result, programs written in any language, using any component model, and running on any operating system can access and utilize Web Services.

In this article we'll take a look at the key foundation concepts of Web Services as well as showing how to both consume Web Services and implement a simple Web Service in the .NET environment.

The Protocols

The key to understanding Web Services is knowledge of the underlying protocols. Importantly, by default, all communications between Web Services servers and clients is through XML messages transmitted over the HTTP protocol. This has 3 benefits:

1. XML text based formatting means these messages are reasonably easy for us humans to read and understand.

2. As HTTP is used these messages will not normally be blocked by firewalls and hence will reach their target destination.

3. XML text based formatting can be interpreted by a wide variety of software on many operating systems.

SOAP

SOAP (Simple Object Access Protocol) is the protocol that allows us to encapsulate object calls as XML. An example SOAP message is:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetArticles xmlns="http://www.cymru-web.net/my_articles_WS/Articles" />
  </soap:Body>
</soap:Envelope>

We'll return to SOAP in later articles.

Disco and UDDI

You need to know where and how to locate a Web Service in order to be able to use it – a process known as discovery. The aim of these two protocols is to facilitate the discovery process.

Disco is a Microsoft standard for the creation of discovery documents. A Disco document is kept in a standard location on a Web Services server (i.e. a web server which hosts Web Services). It contains information such as the path to the corresponding WSDL file (see next section). A Disco document supports static discovery – a potential client must know the location of the document in order to use it.

For VS.NET projects you would not normally use Disco documents as discovery information is available anyway from their base URL, e.g.

http://myServer/myWebService/base_class.asmx?wsdl

would provide discovery information.

However you may also add Disco files to your Web Services project.

UDDI (Universal Description, Discovery, and Integration) is a standardised method of finding web services via a central repository or directory. It applies not only to Web Services but any online resource. UDDI registries are searchable sites that contain information available via UDDI. UDDI provides dynamic discovery – you can discover a Web Service without having to know its location first.

UDDI registries can be private (Intranet based) or public (Internet based). To add your WebServices to a UDDI resgistry you must use the tools provide by the particular registry.

WSDL

WSDL (WebServices Description Language) does what it says – allows description of the Web Service – it specifies the SOAP messages that it can send and receive. The WSDL file defines the public interface of the Web Service: the data types it can process, the methods it exposes and the URLs through which those methods can be accessed.

Here's an example WSDL file, actually from the example later in this article:

<?xml version="1.0" encoding="utf-8" ?>
- <definitions xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:s="http://www.w3.org/2001/XMLSchema"
    xmlns:s0="http://www.cymru-web.net/my_articles_WS/Articles"
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
    xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
    targetNamespace="http://www.cymru-web.net/my_articles_WS/Articles"
    xmlns="http://schemas.xmlsoap.org/wsdl/">
    - <types>
      - <s:schema elementFormDefault="qualified"
          targetNamespace="http://www.cymru-web.net/my_articles_WS/Articles">
          <s:import namespace="http://www.w3.org/2001/XMLSchema" />
          - <s:element name="GetArticles">
              <s:complexType />
          </s:element>
        - <s:element name="GetArticlesResponse">
          - <s:complexType>
            - <s:sequence>
              - <s:element minOccurs="0" maxOccurs="1"
                    name="GetArticlesResult">
                - <s:complexType>
                  - <s:sequence>
                      <s:element ref="s:schema" />
                      <s:any />
                    </s:sequence>
                  </s:complexType>
                </s:element>
              </s:sequence>
            </s:complexType>
          </s:element>
        </s:schema>
      </types>
    - <message name="GetArticlesSoapIn">
        <part name="parameters" element="s0:GetArticles" />
      </message>
    - <message name="GetArticlesSoapOut">
        <part name="parameters" element="s0:GetArticlesResponse" />
      </message>
    - <portType name="ArticlesSoap">
      - <operation name="GetArticles">
          <input message="s0:GetArticlesSoapIn" />
          <output message="s0:GetArticlesSoapOut" />
        </operation>
      </portType>
    - <binding name="ArticlesSoap" type="s0:ArticlesSoap">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
      - <operation name="GetArticles">
          <soap:operation soapAction="http://www.cymru-web.net/my_articles_WS/Articles/GetArticles" style="document" />
        - <input>
            <soap:body use="literal" />
          </input>
        - <output>
            <soap:body use="literal" />
          </output>
        </operation>
      </binding>
    - <service name="Articles">
      - <port name="ArticlesSoap" binding="s0:ArticlesSoap">
          <soap:address location="http://localhost/my_articles_WS/articles.asmx" />
        </port>
      </service>
    </definitions>

We'll return to WSDL in later articles.

Creating A Web Service

I'm going to create a Web Service practical for me ... it's going to return the latest list of the articles I have written. Thus I'll only have to maintain the code and data for this application in one place and the functionality will be easily accessible from the several sites where I need to display this information.

Feel free to choose a small application more useful to yourself whilst implementing via the framework we shall now explore, amending the process accordingly. I'm going to use VS.NET as the IDE for the mini-project. Please adjust for your own IDE and if the IDE amounts to notepad and the command line compiler my former article on Web Services on ASPAlliance may prove useful. This also dovetails nicely into the introduction of the data source of the application: an XML document, a snippet of which will tell you where to find the aforementioned article:

<article
  name="An Introduction to Web Services"
  url="http://www.aspalliance.com/sullyc/articles/intro_to_web_services.aspx"
  PubDate="2003-01-30" />

Thus the Web Service shall load the XML, and XML Schema, from files (see the accompanying links with for sample files to download) and list of articles to the client Web Services consumer, returned as a DataSet object for direct data binding to a DataGrid (in this case - obviously the client is free to do whatever they like with the returned object).

First, create a new project in VS.NET, selecting the ASP.NET Web Service template from the VB Project Type. Specify a location which should be your local web server and an appropriate application name, in my case: HTTP://localhost/my_articles_WS.

VS.NET will create a default Web Service file, service1.asmx which will be visible in the solution explorer. Rename this to something more meaningful to your application, in my case articles.asmx.

Switch to the code view of articles.asmx which will by default already be open within VS.NET. Ensure the class name matches your filename for consistency. Add your code, taking care not to alter any of the VS.NET Web Services designer generated code. Highlighting only the new / key code:

Imports System.Web.Services

<System.Web.Services.WebService(Namespace:="http://www.cymru-web.net/my_articles_WS/Articles")> _
Public Class Articles
  Inherits System.Web.Services.WebService

  <WebMethod()> _
  Public Function GetArticles() As DataSet

    Dim dsDMS As DataSet = New DataSet

    dsDMS.ReadXmlSchema(Server.MapPath("articles_schema.xml"))
    dsDMS.ReadXml(Server.MapPath("articles.xml"))

    Return dsDMS
    dsDMS = Nothing
  End Function

End Class

Note you can change the namespace to your own. As you are probably aware already this should simply be unique – the exact value is unimportant.

Finally build the new Web Service. Easy wasn't it?! VS.NET hides much of the complexity from you meaning you only have to perform 3 actions:

  1. Build your project from the ASP.NET Web Services template.
  2. Write and mark the classes that should be available via the Web Service with the Web Service attribute.
  3. Write and mark the methods that should be available via the Web Service with the WebMethod attribute.

Testing the created Web Service

While you could create a client application to test the Web Service, and we shall shortly, VS.NET includes tools hosted on a web page for testing the Web Service without resorting to the additional overhead of developing a client application.

In VS.NET view your Web Service in Internet Explorer. You'll get the default test page for the Web Service including a list of links to supported operations (in this case one link to GetArticles) and a link to the service description of the Web Service (as used as an example in the WSDL section above).

If you click the GetArticles link you'll be able to invoke the web method and you'll see the dataset returned within the XML SOAP message content.

Consuming a Web Service

How do we consume this Web Service? Let's do this from a web form and display the results in a DataGrid. Ordinarily the Web Service and Web Service client would not exist on the same machine but it makes little difference. Add an ASP.NET web application project to your VS.NET solution.

Add a 'web reference' to the Web Service – right click on the References directory of your project and select 'Add Web Reference'. Locate the Web Service and select 'Add Reference'.

Alter the default web form as follows: add a button named btnInvoke with a label 'Invoke' and a DataGrid named dgArticles to the form. Double click the button and enter the following code to invoke the Web Service when the user clicks the button.

Dim articles As localhost.Articles = New localhost.Articles
dgArticles.DataSource = articles.GetArticles()
dgArticles.DataBind()

View the page in your web browser and you should get the list of articles back, albeit basically formatted. Feel free to tidy up.

Conclusion

That concludes article 1 in this series within which I've provided an introduction to Web Services including examples of creating and consuming them using VS.NET. In the next article we'll delve a little deeper into WebMethods, Disco, UDDI and the available supporting toolset.

References

.NET SDK

Developing XML WebServices and Server Components with VB.NET and the .NET Framework
Mike Gunderloy
Que

You may download the example xml files here.