Introduction to Web Services and ASP.NET


This article has been excerpted from book "The Complete Visual C# Programmer's Guide" from the Authors of C# Corner.

This article is intended only to introduce the ASP.NET and SOAP concepts together, for more details on ASP.NET please refer to the relevant article. A Web service is an application running as a service delivered over the Web. Web services use HTTP and SOAP-encoded XML messages to communicate with clients, which range from Web pages to applications to devices, with the only criteria being that the client can communicate over HTTP in SOAP-encoded XML messages.

The Web Services Description Language (WSDL) is the description of a Web service generated for all Web services. If you are using the .NET platform to create a client, use WSDL.EXE to create a proxy class from the WSDL of the Web service (more about WSDL.EXE in a moment). If you are consuming the Web service over .aspx pages, you need to import the proxy file <%@ Import namespace="AnyService" %>, which should reside in the folder C:\inetpub\wwwroot\Services\bin\.

Once you have the Proxy class code, compile it into a library and use the Proxy class library in your clients to call methods on a Web service. A proxy is a component that acts on behalf of the remote Web service; it allows access to the remote Web service via SOAP and takes care of all the plumbing beneath. The Web service client can use the proxy as a real object and access its properties and methods. When we access a Web service via a proxy, the proxy will convert our Web service call into a SOAP message and send the SOAP request to the Web service. When it receives the raw SOAP-based XML response back from the Web service, it converts the XML response to an object accessible by the client and returns the object to the client.

For the client to use the Web service it should have knowledge of how the Web service is implemented and how to call it. But you can talk to a Web service without knowing how it is implemented. The client cannot know automatically about the Web service. Hence all Web services automatically generate an XML document with WSDL grammar to describe themselves. If you have installed the Web service under a virtual directory called "myservice," you can get the WSDL of the service by calling the following URL in your browser: http://localhost/myservice/service.asmx?WSDL. This will generate an XML file and display it in your browser. The displayed file is the WSDL of the Web service.

The .NET SDK comes with a tool called WSDL.EXE. This tool takes the WSDL of a Web service as an input and uses reflection to generate a Proxy class that is similar to the Web service. You have to reference the System.dll, System.Web.Services.dll, and System.Xml.Serialization.dll assemblies to create your proxy library.

A number of platforms currently exist for creating applications. Each platform has traditionally used its own protocols, usually binary in nature, for machine-to-machine integration. As a result, applications across platforms have only a limited ability to share data. In recognition of these limitations, there has been an overwhelming push toward establishing standards for data formats and for data exchange. This push stems from a vision that is rapidly evolving into a new computing paradigm: the seamless, Web-enabled integration of services across traditional hardware and software barriers. At the heart of this vision is the concept of interoperability, that is, the capacity of disparate systems to communicate and to share data seamlessly. A Web service is a programmable application logic accessible using standard Internet protocols, or to put it another way, the implementation of Web-supported standards for transparent machine-to-machine and application-toapplication communication.

A number of Web services technologies, such as SOAP, WSDL, and HTTP, are now used to pass messages between machines. ASP.NET provides support for Web services with the .asmx file. An .asmx file is a text file similar to an .aspx file. The .asmx files can be part of an ASP.NET application that includes .aspx files. They are then URI addressable, just as .aspx files are. Listing 23.22 shows the file for a "Hello" ASP.NET Web service.

Listing 23.22: "Hello" Web Service


<%
@ WebService Language="C#" Class="Hello" %>

using
System;
using
System.Web.Services;

public
class Hello : WebService
{
    [WebMethod]
    public String SayHello()
    {
        return "Hello!";
    }
}


This file starts with an ASP.NET directive, WebService, and sets the language to C#. Next, the class Hello is declared. This class is derived from the base class WebService. Finally, any methods that will be accessible as part of the service have the custom attribute [WebMethod] in front of their signatures. To make this service available, we might name the file HelloWorld.asmx and place it on a server called XXX.com in a virtual directory called YYY. With virtually any HTML 3.2 or later browser, you could then enter the URL http://XXX.com/YYY/Hello.asmx, and the resulting page would show the public methods for this Web service (those marked with the WebMethod attribute), as well as which protocols (such as SOAP or HTTP GET) you can use to invoke these methods. Entering http://XXX.com/YYY/Hello.asmx?WSDL into the Internet Explorer address bar produces the same information as an XML file, based on the WSDL grammar. This WSDL file is used by clients that access the service and is very important. The WSDL.EXE tool in the .NET SDK (or in the Visual Studio .NET integrated development environment, "Add Web Reference" on the Project menu) can be used to download the WSDL description of a Web service and create a proxy class that addresses the service.

WSDL /language:CS /n:Hello /out:Hello.cs
http://localhost/hello/HelloWorld.asmx?WSDL

A proxy class called Hello.cs is then created. It contains a method called SayHello that returns a string. Compiling this proxy class into an application and then calling its method results in the proxy class's packaging a SOAP request across HTTP and receiving the SOAP-encoded response, which is then marshaled as a string. We could code a client as shown in Listing 23.23.

Listing 23.23: "Hello" Web Service Client


using
Hello;
Hello myHello = new Hello();

Console
.WriteLine(myHello.SayHello());

A Web service allows a site to expose programmatic functionality via the Internet. Web services can accept messages and have the option to return replies to those messages. Today's sites already expose functionality that allows you to do such things as query a database, book an airline reservation, check the status of an order, and so on, but no consistent model exists for allowing you to program against these sites. Web services can be invoked via HTTP POST, HTTP GET, and SOAP is a remote procedure call protocol and specification developed by a group of companies including Microsoft and DevelopMentor. It is based on broadly adopted Internet standards such as XML and typically runs over HTTP.

Visual Studio .NET is the formal shipping vehicle for creating rich Web services on the .NET platform. With the release of Visual Studio .NET (http://msdn.microsoft.com/vstudio/nextgen/default.asp) we are able to create Web services by using ASP+.NET and any language that targets the common language runtime or ATL Server and unmanaged C++. ATL Server is a collection of Active Template Library classes that aid the C++ developer in writing native, unmanaged Internet Server Application Program Interface (ISAPI) extensions and filters. Instead of the .aspx file extension of an ASP Web page, Web services are saved in files with the extension .asmx.

Whenever the ASP runtime receives a request for a file with an .asmx extension, the runtime dispatches the call to the Web service handler. This mapping is established in the <httphandlers> section of the config.web files for the machine and individual applications. Config.web files are human-readable XML files used to configure almost every aspect of your Web applications. Handlers are instances of classes that implement the System.Web.IHTTPHandler interface. The IHTTPHandler interface defines two methods, IsReusable and ProcessRequest. The IsReusable property allows an instance of IHTTPHandler to indicate whether it can be recycled and used for another request. The ProcessRequest method takes an HttpContext object as a parameter and is where the developer of an HTTP handler begins to do his work. A particular handler ultimately services inbound requests that are received by the ASP+ runtime. After a handler is developed, it is configured in the config.web file of the application. A typical config.web file for a machine will have code similar to that shown in Listing 23.24.

Listing 23.24: Sample Config.web File Contents


<
httphandlers>
<
add verb="*" path="*.asmx"
type="System.Web.Services.Protocols.WebServiceHandlerFactory, System.Web.Services"
validate="false" />

</
httphandlers>

In Listing 23.24 the <httphandlers> section states that for all requests (HTTP verbs such as GET, POST, or PUT), if the file being requested has an .asmx extension, create an instance of the WebServiceHandlerFactory, which lives in the System.Web.Services.dll assembly. If the administrator wanted this handler to accept only the GET verb, he or she would change the verb property to verb="Get". Handlers accept requests and produce a response. When the HTTP runtime sees a request for a file with the .aspx extension, the handler that is registered to handle .aspx files is called. In the case of the default ASP installation, this handler will be System.Web.UI.PageHandlerFactory. This is equivalent to how .asmx files are handled. For the default ASP+ installation, Web services are handled by System.Web.Services.Protocols.WebServiceHandlerFactory.

The custom handler enables ASP to use reflection and dynamically create an HTML page describing the service's capabilities and methods. The generated HTML page also provides the user a way to test the Web methods in the service. Another advantage of ASP is seen in publishing Web Service Definition Language contracts. As noted previously, WSDL is an XML-based grammar for describing the capabilities of Web services. WSDL allows a Web service to be queried by potential consumers of your service, you can think of it as an XML-based type library made available via the Web. For output to be generated, one must only make an HTTP request to the Web service file passing in Service Description Language (SDL) in the query string (e.g., http://localhost/services/myservice.asmx?WSDL ). Another nice aspect of the Web service handler is that it creates a simple test Web page for your services. This test page allows you to confirm that everything in your Web service is working without having to write your own test client.

In the next example, we create a Web service that returns the date and time from the server. We could just return the date and time within a string type and force the caller to parse the string, but that would not be ideal. Instead, we are going to create a LocalTime struct that will be returned to the caller. For those of you unfamiliar with structs, they are synonymous with Visual Basic's userdefined types (UDTs). A walkthrough of the code shows us defining a LocalTime struct that contains all the date and time information to be returned to the client. Our LocalTime struct holds eight values: Day, Month, Year, Hour, Minute, Seconds, Milliseconds, and Timezone. The struct's definition is shown in Listing 23.25.

Listing 23.25: TimeService ASP.NET Web Service


<%@ WebService Language="C#" class="TimeService" %>

using
System;
using
System.Web.Services;

public
struct LocalTime
{

public
int Day;
public
int Month;
public
int Year;
public
int Hour;
public
int Minute;
public
int Seconds;
public
int Milliseconds;
public
string Timezone;
}


public
class TimeService
{
[WebMethod]


public
LocalTime GetTime()
{

LocalTime
lt = new LocalTime();
DateTime dt = DateTime.Now;
lt.Day = dt.Day;
lt.Month = dt.Month;
lt.Year = dt.Year;
lt.Hour = dt.Hour;
lt.Minute = dt.Minute;
lt.Seconds = dt.Second;
lt.Milliseconds = dt.Millisecond;
lt.Timezone = TimeZone.CurrentTimeZone.StandardName;

return
lt;
}
}


.NET includes a console application that takes care of requesting the WSDL contract of a remote Web service and generating a proxy to use the service. For you to use a remote Web service a few things need to happen. You need to know where the Web service resides (e.g., http://www.servername.com/wstest.asmx). Then you need to create a local proxy for the remote service. The proxy allows the developer to work with the remote service as though it were local to the machine. When instantiated, the proxy accepts method calls from your code as though it were the remote service object. Calls are packaged into SOAP methods and shipped via HTTP to the remote Web service. If the remote object is created via the specified channel, the remote service receives the request, unwraps the envelope, does the work that you asked, then returns the result in a result envelope. Once the proxy receives this returned envelope, it is unwrapped and delivered to your code as a native method call.

The WSDL.EXE utility takes care of requesting a WSDL contract from a remote Web service via HTTP and generating a proxy class for you. Although the Web services utility uses C# as its default proxy-generation language, any language (including VB and JScript) that implements the ICodeGenerator interface will work (e.g., just change the language parameter to CS for C#.NET, VB for VB.NET, or JS for JS.NET).

WSDL /language:CS /n:TimeService http://localhost/services/TimeService.asmx?WSDL /out:TimeServiceProxy.cs

Running this command generates the TimeServiceProxy.cs file. An instance of this object is what takes care of accepting method calls, packaging up calls for SOAP, invoking via HTTP, and returning the results, if any, to the caller. Now that you have a proxy, you need to compile it using the appropriate compiler (which depends on the language you have chosen). The following command assumes that the C# compiler (csc.exe) is in the system's path and that you are working in the directory where your Web service's .asmx file resides.

csc /out:TimeServiceProxy.dll /t:library /r:system.web.services.dll /r:system.xml.serialization.dll TimeServiceProxy.cs

This command creates a DLL named TimeServiceProxy.dll. Now we will use a Web time service via a .NET application, a simple console application in C# that prints out the time from the remote service. This application is compiled into an executable (.exe) file as opposed to a library (.dll). The TimeTestApp.exe first creates a new instance of our TimeService class that lives in the bin/TimeServiceProxy.dll assembly. Then a call is made to the GetTime method of the TimeService class (ts). The returned value is stored in a local variable named lt. The lt variable is of the type LocalTime. In case it isn't obvious, we should point out that the LocalTime object that we are now using is originally defined in our remote .asmx file. The WSDL utility is able to create a local definition of the LocalTime struct based on the SDL contract that is generated and returned from the Web service handler. Next in our code, we call GetTime and then begin simply to construct a couple of local strings that contain our formatted time and date. Then we output the results using Console.WriteLine. See Listing 23.26.

Listing 23.26: TimeService Web Service Client1

using System;
using
TimeService;

class
MyClass
{
    static void Main()
    {
        TimeService ts = new TimeService();
        LocalTime lt = ts.GetTime();
        string stime = lt.Hour + ":" + lt.Minute + ":" + lt.Seconds + "." +
        lt.Milliseconds + " " + lt.Timezone;
        string sdate = lt.Month + "/" + lt.Day + "/" + lt.Year;
        Console.WriteLine("The remote date is: " + sdate);
        Console.WriteLine("The remote time is: " + stime);
    }
}


To compile the TimeTest application, use the following command.

csc /r:system.web.services.dll /r:TimeServiceProxy.dll TimeTestApp.cs

This command creates an executable file named TimeTestApp.exe in the local directory. We could have explicitly told the C# compiler that we wanted an executable, but the compiler creates executables (/target:exe) by default. We assume you have copied TimeServiceProxy.dll to the C:\inetpub\wwwroot\Services\bin\ directory (the Web services directory under the default IIS installation directory). Thus, a simple draft .aspx Web page file that uses our service can be developed as in Listing 23.27 (note that the code shown is simple; please enhance it depending on your implementations).

Listing 23.27: TimeService Web Service Client2


<%
@ Import Namespace="System" %>
<%
@ Import Namespace="TimeService" %>
<%
@ Page Language="C#" %>

<
html>
<
head>
</
head>
<
body>
    <script language="C#" runat="server">
        public void getDateTime()
        {
            //Create a Instance of the Proxy Class
            TimeService tm = new TimeService();
            LocalTime LT = ts.GetTime();

            // now "LT" contains the time web service returned DateTime value
        }
    </script>

</
body>
</
html>

Conclusion

Hope this article would have helped you in understanding Web Services and ASP.NET. See other articles on the website on .NET and C#.

The Complete Visual C# Programmer's Guide covers most of the major components that make up C# and the .net environment. The book is geared toward the intermediate programmer, but contains enough material to satisfy the advanced developer.


Similar Articles