Thursday, June 12, 2008

webservice part 3

Now how do I use the service?

When Microsoft's Visual Studio.Net ships it will take care of discovering and importing web services for programmatic use, with effort on par with adding a reference in Visual Basic. In the meantime though, the .Net team has created a console application that takes care of requesting the SDL contract of remote web services and generating a proxy to use the service. In order to use a remote web service a few things need to happen.

First you need to know where the web service resides(ex http://www.servername.com/wstest.asmx). Next 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 up into SOAP methods and shipped via HTTP to the remote web service. If everything goes correctly, the remote service receives the request, unwraps the envelope, does the work that you asked it to do, then returns the results 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 Web Services Utility

The wsdl is a console application that is supplied in Microsoft's .Net SDK. The utility takes care of requesting a SDL 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. For us to create a proxy class for accessing my web service we use the command below:

wsdl "http://localhost/services/TimeService.asmx" /out:TimeServiceProxy.cs

The /c: parameter informs the utility that I want it to create a proxy for me. The /pa: parameter is the path to the SDL contract; this can be a local path, UNC path or URI. when we run this command a .cs file will be generated. TimeServiceProxy.cs 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 depending on the language you chose. 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.

On my system the TimeService.asmx file is located at C:\inetpub\wwwroot\Services. Since we are working with C#, the command is (this should be on one line):

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

This command creates a DLL (library) named TimeServiceProxy.dll in the C:\inetpub\wwwroot\Services\bin directory importing the resources System.Web.Services.dll and System.xml.serialization.dll. Once we have the DLL in the bin directory of our ASP.NET application we access the methods of the remote web service as though they were running locally. But this remote web service is not limited to being used only by ASP.NET. Any .Net class can now access our time web service

TimeTest Application

To demonstrate that our time web service is usable by any .Net application, I have created a simple console application in C# that prints out the time from the remote service. This application is compiled into an executable (.exe) 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, I want to point out that the LocalTime object that we are now using was originally defined in our remote .asmx file. The WebServiceUtil was able to create a local definition of the LocalTime struct based on the SDL contract that was generated and returned from the Web Service handler. Next in our code, we call GetTime and then begin to simply construct a couple of local strings that contain our formatted time and date. Then we write out the results using Console.WriteLine:

using System;
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 will create an executable named TimeTestApp.exe in the local directory. We could have been explicit in telling the C# compiler that we wanted an executable, but the compiler creates executables (/target:exe) by default. Another item that should be noted is that although ASP.NET applications look in the bin directory within an ASP.NET application directory to resolve references, non-ASP.NET applications first look in the current directory and then in the system path to resolve assembly references.