Asynchronous Web Services Invocation in .NET Framework 2.0

balecomputerSecurity

Nov 3, 2013 (3 years and 7 months ago)

113 views

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 servi
ces 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 cont
inuing (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 c
alls 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 runnin
g 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 c
an 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 o
f
time to return.


Event
-
Based Asynchronous Programming

Previous versions of the .NET Framework used the B
eginInvoke/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 proper
ties 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 a
nd
view the code, you will find a method named HelloWorld already placed in the code
-
behind file of the Web servi
ce. For the purposes
of this example, just utilize this default sample method. Here is the code from the code
-
behind file of the HelloService:

using System.Web;

using System.Collections;

using System.Web.Services;

using System.Web.Services.Protocols;


[
WebService(Namespace = "http://tempuri.org/")]

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1,


EmitConformanceClaims = true)]

public class HelloService : System.Web.Services.WebService

{


[WebMethod]


public string He
lloWorld()


{


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.

Now that you've created the Web service, if you right click on it and select

View in Browser
, you will see the screen shown
in Figure 1.


(
Full Size Image
)

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 Fo
rms 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

di
alog 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 star
t, import the Web service proxy namespace at the top of the Form1:

using AsyncWebServicesClient.HelloWorldServiceProxy;

To the form, add a command button named btnInvokeHelloWorld and modify the click event of the command button to look as
follows:

private

void btnInvokeHelloWorld_Click(object sender, EventArgs e)

{


HelloService service = new HelloService();


//Hookup async event handler


service.HelloWorldCompleted += new


HelloWorldCompletedEventHandler(this.HelloWorldCompleted);


ser
vice.HelloWorldAsync();

}

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 as
ynchronously
invoke the HelloWorld method.

The new <MethodName>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,


HelloWorldCompletedEventArg
s args)

{


//Display the return value


MessageBox.Show(args.Result);

}

After the Web service has finished its execution and returned the results, the .NET Framework will automatically invoke the a
bove
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 o
f
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. M
odify the code
-
behind of the CategoriesService.asmx file to look as follows:

using System;

using System.Web;

using System.Collections;

using System.Web.Services;

using System.Web.Services.Protocols;

using System.Data;

using System.Data.SqlClient;

using
System.Diagnostics;


[WebService(Namespace = "http://tempuri.org/")]

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1,


EmitConformanceClaims = true)]

public class CategoriesService : System.Web.Services.WebService

{

[WebMethod
]


public DataSet GetCategories()


{


try


{


using (SqlConnection conn = new SqlConnection())


{


string connectionString =


System.Configuration.ConfigurationManager.



ConnectionStrings["northwindConnectionString"].


ConnectionString;


conn.ConnectionString = connectionString;


SqlCommand command = new SqlCommand


("Select * from Categories", conn);


command.CommandType = CommandType.Text;


SqlDataAdapter adapter = new


SqlDataAdapter(command);


DataSet categories = new DataSet("Categories");


adapter.Fill(categories);



return categories;


}


}


catch (Exception ex)


{


EventLog.WriteEntry("Application", ex.Message);


throw ex;


}


}


}

Line
-
by
-
Line Code Breakdown

The above code first encloses the

SqlConnection object within the scope of a using block. Then, it retrieves the connection string
from the ConnectionStrings section of the web.config file:

string connectionString = System.Configuration.ConfigurationManager.


ConnectionStrings["northwi
ndConnectionString"].


ConnectionString;

The code stores the connection string directly under the root <configuration> element in the web.config as follows:

<connectionStrings>


<add name="northwindConnectionString"


connectionString="server=
localhost;uid=sa;pwd=thiru;


database=northwind"/>

</connectionStrings>

Then, it sets the retrieved connection string to the ConnectionString property of the SqlConnection object. After that, the c
ode
creates an instance of the Sq
lCommand 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:

SqlDat
aAdapter 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");

adapter.Fill(
categories);

Finally, it returns the DataSet object back to the caller using the return statement:

return categories;

Now that you have seen the implementation of the Web service, take a look at the client application that will consume the Web

service.

Con
sume 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
as
CategoriesServiceProxy
. Once the Web reference is created, you can import the namespace of the proxy using the
following line:

using
AsyncWebServicesClient.CategoriesServiceProxy;

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:

private void btnInvokeCategories_Click(object sender, EventArgs e)

{


CategoriesService service = new CategoriesService();


service.GetCategoriesCompleted += new


GetCategoriesCompletedEventHandler


(this.GetCategoriesCompleted);


s
ervice.GetCategoriesAsync();

}

The implementation of the GetCategoriesCompleted method is as follows:

void GetCategoriesCompleted(object sender,


GetCategoriesCompletedEventArgs args)

{


//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 lon
g
way toward increasing developer productivity. You can leverage the framework to increase the responsiven
ess 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 imp
lement
the asynchronous Web service invocation feature in your .
NET applications.