Search:
Locator+ Code:
FTPOnline Channels Hot Topics Partner Sites Magazines About FTP RSS 2.0 Feed
 

Web Services

Develop Interface-Based .NET Web Services

Building interface-based Web Services lets you switch between different service providers with minimal or no changes to client code.

by Juval Lowy



s you well know from traditional component-oriented programming, separating the interface from its implementation provides polymorphism between different implementations of the same service. The separation recognizes the fact that the basic unit of reuse in any application is the interface, not the object implementing it. You can apply this core principle of component-oriented programming to Web Service development as well.

Technology Toolbox:
C#, Visual Studio .NET beta 2 or later, Windows 2000 or Windows XP beta 2 or later

In this case, the interface is a logical grouping of method signatures that act as the contract between the client and the Web Service provider. You can then switch between different providers with minimal or no changes to the client code because the client is written against an abstract service definition (the interface) rather than a particular service implementation.

The Web Services standard supports interfaces (referring to them as ports). But by default, Web Services support in .NET is method-based, not interface-based. So VS.NET, as it exists today, doesn't inherently allow you to develop interface-based Web Services. I'll show you the simple steps required—both on the server and client—to compensate for the lack of interface-based Web Services in VS.NET, allowing you to develop and consume interface-based Web Services. But first I'll set up an example scenario.

Suppose you have a Web Service called SimpleCalculator that provides the four basic arithmetic operations—addition, subtraction, division, and multiplication—and a client that consumes the Web Service. You implement the SimpleCalculator Web Service in .NET using C# (see Listing 1).

Simply add the [WebMethod] attribute to the methods you want to expose as Web Services—Add(), Subtract(), Divide(), and Multiply()—and .NET does the rest. Note that having WebService as a base class is optional; deriving from it gives you easy access to common ASP .NET objects, such as those for application and session states. You don't need these objects in this use-case. Also optional is the WebService attribute, but I strongly recommend you use it.

The WebService attribute lets you specify a Web namespace that contains your service, which you can use as you would a normal .NET namespace to reduce name collusion. If you don't specify a namespace, VS.NET uses http://tempuri.org/ as a default. A published service usually uses a specific Uniform Resource Identifier (URI) as its namespace, typically the service provider company's name. The WebService attribute also allows you to provide a free-text description of your service that appears in the auto-generated browser page used by Web Service consumers and during development.

Writing the client code is almost equally trivial. Select Add Web Reference… from the client's project in VS.NET and point the wizard at the site containing the Web Service ASPX file. This makes VS.NET generate a wrapper class—called SimpleCalculator—that the client will use (see Listing 2). The SimpleCalculator wrapper class has all the methods the Web Service developer applied [WebMethod] to as public methods. The wrapper class (sometimes called a "Web Service Proxy" class) encapsulates completely the complex interaction with the remote object. The wrapper class is also the only entity coupled to the service's location—its base class, SoapHttpClientProtocol, has a property called Url that points to the object's location.

The client code uses the wrapper class as if the SimpleCalculator object were a local object:

SimpleCalculator calculator;
calculator = new SimpleCalculator();
int result = calculator.Add(2,3);
Debug.Assert(result == 5);

Clearly, VS.NET makes invoking Web methods trivial.

But you have a problem: The client ends up programming directly against the "object" providing the service (SimpleCalculator in this case) instead of against a generic abstraction of such a service. You want the SimpleCalculator Web Service polymorphic with a service abstraction—an interface.

For example, imagine the client wants to switch from the SimpleCalculator to a different calculator Web Service, called ScientificCalculator. ScientificCalculator supports the same interface as SimpleCalculator, but it's perhaps faster, cheaper, or more accurate. You'd like to define a generic calculator interface, the ICalculator interface, and expose it as Web Service:

// Imaginary attribute. 
// Does not exist in .NET
[WebInterface]
interface ICalculator
{
   int Add(int num1,int num2);
   int Subtract(int num1,int num2);
   int Divide(int num1,int num2);
   int Multiply(int num1,int num2);
} 

Assuming you could do that (I'll show you how shortly), you can code against only the interface definition instead of a particular implementation of it (see Listing 3).

The only thing that changes in the client's code when it switches between service providers is the line that decides the exact interface implementation to use. You can even put that decision in a different assembly than the "main" client's logic, and you can only pass interfaces between the two. Another benefit you can reap from interface-based Web Services: The client can publish the interface definition, enabling different service vendors to implement the client's requirements more easily.

Now you're ready to write the server and client code to work around VS.NET's lack of support for interface-based Web Services.

 
Define and Implement a Web Interface

In this Article
Introduction Write the Client-Side Code
Define and Implement a Web Interface