Web Service Example

In this example we will create a simple Calculator web service that exposes one function—GetRandomNumber(). Web services require that ASP.NET and IIS are installed on the host machine. Both of these products should be installed automatically by the .NET Framework setup.

The first step is to create a directory on your machine that will house your web service (call it C:\MyWebService). The IIS Configuration tool is then used to turn this directory into a virtual directory, which makes files stored in C:\MyWebService accessible to IIS and ASP.NET. Launch the IIS Configuration manager by going to Start Menu ^ Programs ^ Administrative Tools ^ Internet Services Manager. Right-click on Default Web Site. Selecting New ^ Virtual Directory from the popup menu launches the Virtual Directory Creation Wizard. You will be prompted to give the directory an alias (enter MyService), as well as the actual location of the directory on your machine (enter C:\MyWebService). The creation of the virtual directory is now complete, and all files in C:\MyWebService are available to IIS and ASP.NET via the URI http://localhost/MyService/.

The next step is to implement the actual web service. Using your favorite text editor, create a file in C:\MyWebService called Calculator.asmx. Note that web services are characterized by the .asmx file extension, whereas ASP.NET pages (Chapter 8) have the extension .aspx. As stated at the beginning of this example, our web service will expose one function called getRandomNumber(), which accepts two floating-point parameters x and y, and returns a random floating point number in-between. Copy the following C# source code into Calculator.asmx. A VB.NET equivalent can be obtained at aNET090001.

<%@ WebService Language="C#" Class="CodeNotes.Calculator" %>

namespace CodeNotes { using System;

using System.Web; // Need these two references using System.Web.Services; // for Web Services.

[WebService(Namespace=

"http://www.codenotes.com/webservices/")]

public class Calculator {

[WebMethod(Description=

"Generates a random number between x and y")]

public double getRandomNumber(double x, double y) {

Random r = new Random(); double randDouble = r.NextDouble(); double returnVal = (y - x) * randDouble + x; return returnVal;

Listing 9.1 Calculator web service (Calculator.asmx)

Notice that the Calculator class in Listing 9.1 follows virtually the same C# syntax that we have used to create other .NET components. Three new syntax features, which are bolded in Listing 9.1, are added to transform the Calculator class into a bona fide web service.

1. <%@ WebService Language="C#" Class="CodeNotes. Calculator" %>. Typically, a web service such as Calculator .asmx remains uncompiled on the server until it is accessed. When a web service is first accessed, it is Just In Time (JIT) compiled by ASP.NET. The <%@ WebService %> descriptor is used to specify the language in which the service is written (C#), as well as the class that is to be exposed (CodeNotes.Cal-culator). ASP developers will recognize the <% and %> tags used to denote information intended for the web server.

When the Calculator service is first called, ASP.NET will parse the <%@ WebService %> line and invoke the C# compiler (csc.exe) to compile the Calculator class. Alternatively, you do have the option of precompiling your class into an assembly. See the How and Why section at the end of this example for details.

2. [WebService(Namespace="http://www.codenotes.com/web services/")]. The WebService attribute is used to define the XML namespace for a web service. If you are unfamiliar with attributes, please refer to the Attributes section in Chapter 4. As discussed in the Core Concepts section above, XML namespaces uniquely define a collection of predefined XML elements. In this case, the predefined elements are the methods exposed by the web service.

The application of the XML namespace will be examined in more depth in the WSDL section of this chapter. At this point, it is important to note two points about the web service XML namespace. First, the namespace is required to ensure that the GetRandomNumber() method of our Calculator class is unique, as compared to any other Calculator web services on the Internet. Secondly, the specified namespace (in this case http://www.codenotes.com/webservices/) does not represent the location of a resource on the Web—the namespace could just as easily have been declared as:

[WebService(Namespace="SomeServiceXYZ")]

URLs, however, are typically used for XML namespace, since they are inherently unique.

3. [WebMethod(Description="Generates a random number between x and y")]. Every method exposed by a web service must be marked with the [WebMethod] attribute. The [WebMethod] attribute alone transforms the class method into a Web-callable one. The optional Description parameter, on the other hand, allows the developer to provide a human-readable description of the method's functionality. In a later section of this chapter, Other Web Service Features, we will discuss additional [Web-Method] parameters used to manage state and transactions for a web service method.

The [WebMethod], [WebService], and <% WebService %> descriptors transform the C# Calculator class into a Calculator web service. The remaining lines in Listing 9.1 are straightforward C#. The System .Random class is used to return a random number within the interval specified by parameters x and y.

To invoke the web service, launch Internet Explorer and navigate to http://localhost/ MyService/Calculator.asmx. ASP.NET creates a default page that depicts the methods exposed by Calculator.asmx, along with a link called "Service Description." The Service Description is the WSDL (an XML interface) for this web service and is discussed in detail in the WSDL section of this chapter. Click onGetRandomNumber() to obtain the following screen:

Figure 9.1 Accessing our web service through IE

Note that the Description parameter of the [WebMethod] attribute we specified in Listing 9.1, "Generates a random number between x and y," is parsed by ASP.NET, and appears in Figure 9.1.

Below the description, ASP.NET lists the parameters accepted by the GetRandomNumber() method, and displays entry fields allowing you to invoke the method for test purposes. Scroll down the default page, and note the sections with headings "SOAP", "HTTP POST," and "HTTP

GET." These three sections present example request and response messages in the format required to access the web service. Keep these formats in mind, as we will use this information in the following section, HTTP POST and SOAP.

Test the GetRandomNumber() method by entering values for x and y (say, 0 and 100), and click Invoke. Doing so will bring up a screen with the response from the service. Figure 9.2 shows the output obtained from the GetRandomNumber() method call.

Figure 9.2 GetRandomNumber() results

Notice that GetRandomNumber() returned its result in XML format; this is true for all web service methods. Also note that the XML element containing the random number uses the XML namespace we specified with the [WebService] attribute (Listing 9.1). This namespace distinguishes the result returned by our component from results returned by other web services.

Look closely at the URL in Figure 9.2 and you will see that the x and y values you specified are embedded into the URL itself. From the Core Concepts section of this chapter, you should recognize this format as an HTTP GET request. When the Invoke button (Figure 9.1) was clicked, the following sequence of events occurred:

1. The browser (Internet Explorer, in our case) reads the x and y values from the fields in the HTML page and sends out the following HTTP GET request: http://localhost/myservice/ Calculator.asmx/GetRandomNumber?x=0&y=100

2. IIS and ASP.NET determine that the request is for the Calculator component located in the MyService virtual directory. (Recall that this actually points to the directory C:\MyWebService on the local machine.)

3. If the web service is being requested for the first time, ASP.NET JIT-compiles the component according to the first line in Listing 9.1. Remember the <%@ WebService %> descriptor instructed

ASP.NET to use the C# compiler (csc.exe) to build the Calculator component. After compilation, ASP.NET delivers the following HTTP GET request to the Calculator component:

GET /myservice/Calculator.asmx/GetRandomNumber?x=0&y=100 HTTP/1.1

Remember that adding the <%@ WebService %>, [WebService] and [WebMethod] tags transformed our C# Calculator class into a web service. One virtue of a web service is that it inherently interprets HTTP requests behind the scenes. The Calculator service determines that a client is calling the GetRandomNumber() method with parameters x=0 and y=100. The Calculator service executes the method to produce a random number between 0 and 100.

4. The Calculator web service packages the result into the XML format of Listing 9.3. This result is returned to the ASP.NET Runtime with the instruction that it be delivered to the client.

5. IIS sends the XML result over HTTP back to the client (in this example, the web browser).

The above steps certainly seem like a roundabout method of obtaining a random number! This scenario is more impressive, however, if you realize that the client could have been anywhere (across the room, across the ocean), and the exposed method could have done anything (queried a database, traded a stock, etc.). Also keep in mind that our client does not have to be a web browser. It can be any application capable of sending HTTP over the Internet. In addition, parameter methods can be transferred using more sophisticated mechanisms such as HTTP POST and SOAP. The next topic will examine these two protocols in detail.

HOW AND WHY Can My Web Service Class Reside in a Compiled Assembly?

In the previous example we didn't compile Calculator.asmx. Instead, the ASP.NET Runtime JIT-compiled the class when the GetRandomNumber() method was first called. Situations may arise where you want ASP.NET to invoke a web service that is already compiled. One such scenario is when you want to write a web service in managed C++. Unfortunately, ASP.NET can only JIT-compile components written in C#, VB.NET, or JavaScript (by using the Language="C#/VB/JS", options of the WebService attribute, respectively).

To expose a C++ version of the Calculator component as a web service (the source code can be found at aNET090002), compile it into an assembly using the Visual C++ compiler:

cl /CLR /LD Calculator.cpp

Place the Calculator.DLL assembly file that is produced in the virtual root's bin directory (C:\MyWebService\bin in our example). Now create a text file called CalcCpp.asmx in C:\MyWebService that contains the following line:

<%@ WebService Class="CppCalc.CalcClass,Calculator"%>

The highlighted portion of the line above tells ASP.NET that the web service resides in the Calculator.DLL assembly (ASP.NET automatically looks in the bin directory for it). Note that when specifying the assembly name, you omit the DLL extension. Also note that we do not specify a Language, since ASP.NET will be executing code that is already compiled.

Point your browser to http://localhost/myservice/CalcCpp.asmx and ASP.NET will run the managed C++ class as a web service. This technique can also be used on languages that are not supported by ASP.NET but may produce IL code in the future (COBOL, Java, etc.). You can, if you wish, also use this procedure on classes written in C#, VB.NET, and JavaScript. Because the component is already in an assembly, the initial delay time it takes ASP.NET to JIT-compile it (the first time it is invoked) is eliminated. This is an especially attractive option if target class is large and complex.

0 0

Post a comment