Team LiB
Previous Section Next Section

Adding Web References

Whether you are creating a Web Application or a Windows Forms application, you will need to provide some method by which your code accesses a web service. Thankfully, with .NET, you don't have to write your own SOAP headers and send your own manually created HTTP messages. The .NET Framework enables you to communicate with a web service via a proxy class that is generated on your behalf. You can generate this code proxy in one of two ways: via Web References in Visual Studio .NET or via a command-line tool called WSDL.EXE. This next section will show you how to create this proxy class using both methods.

Adding References in Visual Studio .NET

The easier of the two methods of creating a proxy for a web service is to use Visual Studio .NET's built-in features. To make use of a web service from within Visual Studio .NET, first create a new Windows Forms application.

When you have a new application, right-click the References folder and choose Add Web Reference. You will then be prompted with the search dialog box shown in Figure 18.1. This dialog enables you to supply the URL for a web service that you want to consume. When you are satisfied that you are looking at the correct service, clicking the Add Reference button will create a proxy class for you.

Figure 18.1. Visual Studio .NET 2003's Add Web Reference dialog.


To see that you have had a special class created for you, go to the solution explorer and choose Show All Files. At this point, the Web References folder will appear, with the HelloService web service node. Beneath that you will see three more files: Hello.disco, Hello.wsdl, and a node called Reference.map. These names were all generated automatically. When you create a web reference, you can choose the name of that web reference from the dialog box. This name becomes a namespace qualifier for the proxy class that has been created for you.

To continue exploring the new reference, expand the Reference.map node and you will see a file called Reference.cs. This sample is a deliberately simple web service (the ubiquitous Hello World service) so that you can see the generated proxy class without wading through 30 pages of code. Listing 18.1 shows this auto-generated proxy class. As you can see, it contains both synchronous and asynchronous method invocations for the three methods of the web service: Ping, HelloWorld, and SlowHelloWorld.

Listing 18.1. The Visual Studio .NET Auto-Generated Web Service Client Proxy
//------------------------------------------------------------------------------
// <autogenerated>
//     This code was generated by a tool.
//     Runtime Version: 1.1.4322.573
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </autogenerated>
//------------------------------------------------------------------------------

//
// This source code was auto-generated by Microsoft.VSDesigner, Version 1.1.4322.573.
//
namespace HelloConsumer.HelloService {
using System.Diagnostics;
using System.Xml.Serialization;
using System;
using System.Web.Services.Protocols;
using System.ComponentModel;
using System.Web.Services;


/// <remarks/>
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(
  Name="HelloSoap", Namespace="http://tempuri.org/")]
public class Hello : System.Web.Services.Protocols.SoapHttpClientProtocol {

/// <remarks/>
public Hello() {
this.Url = "http://localhost/HelloService/Hello.asmx";
}

/// <remarks/>
[System.Web.Services.Protocols.SoapDocumentMethodAttribute( 
  "http://tempuri.org/Ping",
   RequestNamespace="http://tempuri.org/",
   ResponseNamespace="http://tempuri.org/",
   Use=System.Web.Services.Description.SoapBindingUse.Literal,
   ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public bool Ping() {
  object[] results = this.Invoke("Ping", new object[0]);
  return ((bool)(results[0]));
}
/// <remarks/> 
public System.IAsyncResult BeginPing(System.AsyncCallback callback, object asyncState) {
  return this.BeginInvoke("Ping", new object[0], callback, asyncState);
}

/// <remarks/>
public bool EndPing(System.IAsyncResult asyncResult) {
  object[] results = this.EndInvoke(asyncResult);
  return ((bool)(results[0]));
}

/// <remarks/>
[System.Web.Services.Protocols.SoapDocumentMethodAttribute(
  "http://tempuri.org/HelloWorld",
  RequestNamespace="http://tempuri.org/",
  ResponseNamespace="http://tempuri.org/",
  Use=System.Web.Services.Description.SoapBindingUse.Literal,
  ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public string HelloWorld() {
  object[] results = this.Invoke("HelloWorld", new object[0]);
  return ((string)(results[0]));
}

/// <remarks/>
public System.IAsyncResult
  BeginHelloWorld(System.AsyncCallback callback, object asyncState) {
  return this.BeginInvoke("HelloWorld", new object[0], callback, asyncState);
}

/// <remarks/>
public string EndHelloWorld(System.IAsyncResult asyncResult) {
  object[] results = this.EndInvoke(asyncResult);
  return ((string)(results[0]));
}

/// <remarks/>
[System.Web.Services.Protocols.SoapDocumentMethodAttribute(
  "http://tempuri.org/SlowHelloWorld",
  RequestNamespace="http://tempuri.org/",
  ResponseNamespace="http://tempuri.org/",
  Use=System.Web.Services.Description.SoapBindingUse.Literal,
  ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public string SlowHelloWorld() {
  object[] results = this.Invoke("SlowHelloWorld", new object[0]);
  return ((string)(results[0]));
}

/// <remarks/>
public System.IAsyncResult BeginSlowHelloWorld(
  System.AsyncCallback callback, object asyncState) {
  return this.BeginInvoke("SlowHelloWorld", new object[0], callback, asyncState);
}

/// <remarks/>
public string EndSlowHelloWorld(System.IAsyncResult asyncResult) {
  object[] results = this.EndInvoke(asyncResult);
  return ((string)(results[0]));
}
}
}

This chapter is not about how to create complex or advanced web services. It is about the various ways in which you can intelligently consume any service to provide a valuable user experience. As such, the server-side examples that are dealt with throughout this chapter are far more simplistic than real-world services in order to focus on the client-side consumption.

With this web reference in place, drop a simple button onto the main form and change the text to Hello World. Double-click it to generate the following event handler:

private void btnHelloWorld_Click(object sender, System.EventArgs e)
{
  HelloService.Hello helloProxy = new HelloService.Hello();
  MessageBox.Show(this,
    "Web Service returned " + helloProxy.HelloWorld(),
    "HelloService.Hello Proxy");
}

As you can see, you create the web service proxy just as you do any other managed class. The name you supplied in the Web Reference dialog becomes the namespace name, and the name of the service (in this case, the name is Hello) becomes the class name. To use a standard synchronous method invocation, just call the method and handle the results. You'll see more about asynchronous invocation later in this chapter. Figure 18.2 shows the message box created by this simple invocation.

Figure 18.2. MessageBox demonstrating a simple web service invocation.


This section has shown you how to use the built-in Visual Studio .NET 2003 tool to generate a proxy from a web service. Next you'll see how to use the WSDL command-line tool.

Using WSDL.EXE

You might occasionally run into a situation in which you have some special needs surrounding your client proxy. You might need to generate the class outside of Visual Studio .NET, or you might want to generate the class into a precompiled assembly and then simply reference that assembly from within Visual Studio .NET. For whatever reason, if you need manual control over proxy generation, WSDL is the tool to get it done.

As with all .NET command-line tools, running them at the command prompt gives you the basic syntax for operation. In this case, we want to use WSDL.EXE to grab the WSDL (Web Services Definition Language; the discussion of WSDL syntax is beyond the scope of this chapter) from the web service and generate a client proxy. With the sample "Hello World" service in place, the following command was issued to create the proxy:

wsdl /language:CS /namespace:HelloServiceWSDL /o:HelloServiceWSDL.cs
http://localhost/HelloService/Hello.asmx?wsdl

This command tells the WSDL tool to generate a client proxy using the namespace HelloServiceWSDL with an output file of HelloServiceWSDL.cs, using the WSDL contract defined at the URL http://localhost/HelloService/Hello.asmx?wsdl. By appending ?wsdl to the end of a .NET web service URL, you get the raw WSDL contract for the service instead of the friendly greeting page that you get without that parameter.

The important thing to note about this class is that you can get more flexibility and more power by obtaining the reference manually, but it is easier to use from within Visual Studio .NET 2003. Which method you use is up to you, but you can be sure that the code generated for each proxy will be syntactically identical.

The Internet would be one really boring place if the only thing we ever did with web services was say "Hello World." The truth is that web services are far more complex than that. They take longer to return results, the results are more complicated, and the way in which client applications make use of them is almost always more complex. The rest of this chapter will show you best practices, tips, techniques, and code for consuming web services for professional-grade applications.

    Team LiB
    Previous Section Next Section