Asynchronous Web Services Invocation in .NET Framework 2.0
When first introduced, Web services presented a novel way to exchange data between distributed systems. Over the years, Web services have matured tremendously and have moved out of the realm of simply being novel and into the realm of being enterprise-capable. As a result, more and more companies around the world are using Web services to integrate their systems.
As the use of Web services increases, the importance of knowing how to consume services in a scalable and efficient manner becomes paramount, especially given that services can be called synchronously and asynchronously. Applications making synchronous Web service calls send data to a service and wait for the results to return before continuing (see Figure 1). Asynchronous calls, on the other hand, allow multiple Web service calls to be made while the application continues to execute other operations, such as querying a database or reading a file (see Figure 2). As a result, asynchronous calls can increase an application s overall performance in some cases. This increase is typically seen in applications running on multi-CPU servers. A perceived increase in performance by end users may also be seen on single-CPU client systems (those running Windows Forms applications, for instance) when asynchronous techniques are used.
Figure 1:Synchronous Web service calls result in an application waiting until a Web service call returns. While these types of calls work well in many situations, they can be inappropriate when a Web service takes a variable amount of time to return data or when multiple Web services must be called in parallel.
Figure 2:Asynchronous calls allow a Web service to be called while the application continues executing other tasks. It can be useful in cases where multiple Web services need to be called simultaneously or when a Web service call may take a variable amount of time to return.
Event-Based Asynchronous Programming
Previous versions of the .NET Framework used the BeginInvoke/EndInvoke methods to invoke a Web service asynchronously. Version 2.0 adds a new way to asynchronously invoke Web services: an event-based asynchronous programming model. It enables this new event programming model through the creation of properties and methods on the client proxy class.
To follow the demonstration for implementing this model, you must first create a simple Web service that then can be invoked asynchronously from the client application. The following section walks you through the process.
Create a Simple Web Service
Open Visual Studio 2005 and select New->Web Site from the File menu. In the New Web Site dialog box, select ASP.NET Web service from the list of project templates, and specify the name of the Web service as AsyncWebServices.
Once you have created the Web site, add a new Web service file named HelloService.asmx to the project. If you open the file and view the code, you will find a method named HelloWorld already placed in the code-behind file of the Web service. For the purposes of this example, just utilize this default sample method. Here is the code from the code-behind file of the HelloService:
public class HelloService : System.Web.Services.WebService
public string HelloWorld()
return "Hello World";
Note: When you create a Web service through Visual Studio 2005, the code-behind file for the Web service is automatically placed in the App_Code directory, which is a new directory in ASP.NET 2.0 that acts as a container for all the reusable classes in an ASP.NET Web application.
Figure 1. View Newly Created Web Service in Browser
If you click on the HelloWorld method, you will see the screen shown in Figure 2.
(Full Size Image)
Figure 2. View HelloWorld Method in Browser
Clicking on the Invoke button in the Figure 2 results in the screen shown in Figure 3.
(Full Size Image)
Figure 3. Invocation of HelloWorld Method
Figure 3 shows the output produced by the HelloWorld method. Now that you have implemented and tested the Web service, you can move on to the client application that will consume the Web service.
Consume the Web Service Asynchronously from a Windows Forms Application
In this section, you create a Windows Forms application to consume the Web service. Create a new Visual C# Windows Forms application named AsyncWebServicesClient. Next, add a Web reference to the CategoriesService by selecting Project->Add Web Reference from the menu. In the Add Web Reference dialog box, enter the location of the Web service and hit GO. Then, specify the name of the Web reference as HelloWorldServiceProxy, as shown in Figure 4.
(Full Size Image)
Figure 4. Specify the Name of the Web Reference as HelloWorldServiceProxy
Now you are ready to consume the Web service. To start, import the Web service proxy namespace at the top of the Form1:
To the form, add a command button named btnInvokeHelloWorld and modify the click event of the command button to look as follows:
The above code shows the event handler HelloWorldCompleted (that is available through the proxy of the Web service) being hooked up to a local method named HelloWorldCompleted. The method named HelloWorldAsync provides a way to asynchronously invoke the HelloWorld method.
The new Async provides a seamless way to asynchronously consume the Web service from a client application. For example, if you have a Web service method named GetCategories and you want to leverage the asynchronous invocation framework, you need to do two things:
Create an event handler for the GetCategoriesCompleted method and hook it up to a local method that can process the results returned by the Web service.
Invoke the Web service method by calling the GetCategoriesAsync() method through the Web service proxy.
The local HelloWorldCompleted method is defined as follows:
void HelloWorldCompleted(object sender,
//Display the return value
After the Web service has finished its execution and returned the results, the .NET Framework will automatically invoke the above HelloWorldCompleted method. As you can see, this method takes two arguments: an object of type "object" and a "HelloWorldCompletedEventArgs" object. You can capture the results returned by the Web service by using the Result property of the HelloWorldCompletedEventArgs object (as shown in the above code). In this example, the output the Web service returns is displayed in a message box.
Implement Data Binding with a Web Service
Apart from the new Web service asynchronous invocation framework, .NET Framework 2.0 also introduces a new feature through which you can perform data binding, with the results returned from the Web service in a seamless manner. This section demonstrates this feature with a practical example. It begins by creating the Web service.
Implementation of the Web service
To start, add a new Web service to the AsyncWebServices project by right-clicking on the project and selecting Add New Item from the context menu. In the Add New Item dialog box, select Web service from the list of templates and name the Web service CategoriesService.asmx. Modify the code-behind of the CategoriesService.asmx file to look as follows:
Then, it sets the retrieved connection string to the ConnectionString property of the SqlConnection object. After that, the code creates an instance of the SqlCommand object, passing to its constructor the SQL statement to be executed and the SqlConnection object as arguments. Then, it sets the CommandType property of the SqlCommand object to CommandType.Text to indicate that it wants to execute a SQL statement through the SqlCommand object:
SqlCommand command = new SqlCommand("Select * from Categories", conn);
command.CommandType = CommandType.Text;
Next, it creates an instance of the SqlDataAdapter and passes in the SqlCommand object to its constructor:
SqlDataAdapter adapter = new SqlDataAdapter(command);
After that, the code creates a DataSet object and then supplies the DataSet object as an argument to the Fill method of the SqlDataAdapter object:
DataSet categories = new DataSet("Categories");
Finally, it returns the DataSet object back to the caller using the return statement:
Now that you have seen the implementation of the Web service, take a look at the client application that will consume the Web service.
Consume the Web Service from the Client
Open the previously created AsyncWebServicesClient project from Visual Studio 2005. Add a Web reference to the CategoriesService by selecting Project->Add Web Reference from the menu. In the Add Web Reference dialog box, enter the location of the Web service and specify the name of the Web reference asCategoriesServiceProxy. Once the Web reference is created, you can import the namespace of the proxy using the following line:
Next, open Form1 and drag and drop a DataGrid control onto the Form designer. Add another command button named btnInvokeCategories to the form and modify the code in the Click event to look like the following:
CategoriesService service = new CategoriesService();
service.GetCategoriesCompleted += new
The implementation of the GetCategoriesCompleted method is as follows:
void GetCategoriesCompleted(object sender,
//Bind returned results to the UI data grid
dataGrid1.DataSource = args.Result;
As you can see, the DataSet returned from the Web service is directly bound to a DataGrid control and displayed on the form. If you run the form and click on the Invoke Categories Service button, you will see the output shown in Figure 5.
(Full Size Image)
Figure 5. Run the Form and Click on the Invoke Categories Service Button
As Figure 5 shows, the categories information that the Web service returns is directly data bound to the DataGrid control.
Increase Developer Productivity, Enhance User Experience
The new asynchronous invocation framework that .NET Framework 2.0 introduced is an extremely useful feature that can go a long way toward increasing developer productivity. You can leverage the framework to increase the responsiveness of a .NET application, which greatly enhances the user experience as well.
This tutorial provided a thorough discussion of the asynchronous Web service invocation features of .NET Framework 2.0 and provided examples. It also showed how to perform data binding with the results returned from a Web service. Although the application you created was simple in functionality, it should provide a solid foundation for understanding how to easily implement the asynchronous Web service invocation feature in your .NET applications.