January 2018 : Instructor-led Online Course in ASP.NET Core 2.0. Conducted by Bipin Joshi. Read more...
Registration for January 2018 batch of ASP.NET Core 2.0 instructor-led online course has already started. Conducted by Bipin Joshi. Register today ! Click here for more details.

Consuming Web Service using ASP.NET AJAX

Introduction

ASP.NET AJAX is all set to provide the power of Asynchronous JavaScript and XML to your web sites. AJAX makes the web pages more responsive and interactive by reducing the page refreshes or post backs. AJAX harnesses the power of client side JavaScript and XML HTTP object to provide these features. Though AJAX is essentially a client side technique most of the real world cases call for server side processing. Most commonly the data manipulated by your web site will be residing in some RDBMS on the server. To make AJAX really useful there has to be a easy and robust way to deal with this server side data. Fortunately ASP.NET AJAX provides a sound infrastructure to do just that. AJAX communication happens between your browser and the server over internet. Naturally, web services can play a significant role in data transport and overall communication between client and the server. In this article we are going to see how ASP.NET AJAX can consume ASP.NET Web Services.

Example Scenario

As an example we will develop a web form that acts as a data entry page for Employees table of Northwind database. We will a web service that will allow us to SELECT, INSERT, UPDATE and DELETE employees. This web service will be consumed our data entry page using ASP.NET AJAX features. 

Creating web service

To begin with, create a new web site using Visual Studio 2005. Notice that installing ASP.NET AJAX will add certain project templates to the New Web Site dialog.  The Figure 1 shows the New Web Site dialog with the templates I just mentioned.

The web site created using the "ASP.NET AJAX Enabled Web Site" template is different than normal Web Site in the following ways:

  • It has a web.config file with lot of ASP.NET AJAX specific configuration information
  • It refers System.Web.Extensions assembly

Of course, you can modify a normal web site to make it AJAX enabled but this template simplifies your job.

Now that you have created a new web site, add a new web service to it and name it as EmployeeService.asmx. The EmployeeService will contain five web methods. These web methods are mentioned in the following table.

Method Name Description
GetEmployees() This method returns a list of employees from Employees table. The list is returned in the form of an array of Employee objects
GetEmployee() This method accepts an EmployeeID and returns its details as an Employee object
Insert() This method adds a new employee to the Employees table
Update() This method updates an existing employee from the Employees table
Delete() This method deletes and existing employee from the Employees table

The GetEmployees() and GetEmployee() methods return data in the form of Employee object(s). Hence, first you need to create a class called Employee. To do so, right click on the App_Code folder of your web site and choose "Add New Item...". Using the "Add New Item" dialog add a new class called Employee. The complete code that makes the Employee class is shown below:

public class Employee
{
    private int intEmployeeID;
    private string strFirstName;
    private string strLastName;
    public int EmployeeID
    {
        get
        {
            return intEmployeeID;
        }
        set
        {
            intEmployeeID = value;
        }
    }
    public string FirstName
    {
        get
        {
            return strFirstName;
        }
        set
        {
            strFirstName = value;
        }
    }
    public string LastName
    {
        get
        {
            return strLastName;
        }
        set
        {
            strLastName = value;
        }
    }
}

The Employee class declares three provate variables for storing employee id, first name and last name respectively. The three variables are wrapped inside three public properties namely EmployeeID, FirstName and LastName.

Open web.config file and add a <connectionStrings> section as shown below:

<connectionStrings>
<add name="connstr" connectionString=
"data source=.\sqlexpress;
initial catalog=northwind;
integrated security=true"/>
</connectionStrings>

Here, we store a database connection string that points to the Northwind database. Make sure to change SQL Server name/IP and authentication details to match your environment.

Now open EmployeeService.cs and add the following code:

private string strConn =        
   "";
public EmployeeService()
{
strConn = ConfigurationManager.ConnectionStrings ["connstr"].ConnectionString;
}

The code reads the connection string from the config file using ConfigurationManager class and stores it in a class level variable called strConn. This variable is used further by all the other web wethods.

Now add GetEmployees web method as shown below:

[WebMethod]
public Employee[] GetEmployees()
{
SqlConnection cnn = new SqlConnection(strConn);
cnn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = cnn;
cmd.CommandText = "select employeeid,firstname, lastname from employees";
SqlDataReader reader = cmd.ExecuteReader();
List<Employee> list = new List<Employee>();
while (reader.Read())
{
Employee emp = new Employee();
emp.EmployeeID = reader.GetInt32(0);
emp.FirstName = reader.GetString(1);
emp.LastName = reader.GetString(2);
list.Add(emp);
}
reader.Close();
cnn.Close();
return list.ToArray();
}

The code creates a new SqlConnection and SqlCommand objects. It then executes a SELECT query and fetches EmployeeID, FirstName and LastName columns from Employees table. The results are retrieved as SqlDataReader instance. Then a generic based List of Employee objects is created. A while loop iterates through the SqlDataReader. With each iteration a new Employee object is created and its EmployeeID, FirstName and LastName properties are set. The Employee object is then added to the List. After the while loop is over, SqlDataReader and SqlConnection are closed. The return type of GetEmployees() web method is an array of Employee objects. Hence, the generic List is converted into Employee array using ToArray() method of List class.

Next, add a web method called GetEmployee() as shown below:

[WebMethod]
public Employee GetEmployee(int pEmployeeId)
{
SqlConnection cnn = new SqlConnection(strConn);
cnn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = cnn;
cmd.CommandText = "select employeeid,firstname, lastname from employees where employeeid=@id";
SqlParameter id = new SqlParameter("@id", pEmployeeId);
cmd.Parameters.Add(id);
SqlDataReader reader = cmd.ExecuteReader();
Employee emp = new Employee();
while (reader.Read())
{
emp.EmployeeID = reader.GetInt32(0);
emp.FirstName = reader.GetString(1);
emp.LastName = reader.GetString(2);
}
reader.Close();
cnn.Close();
return emp;
}

The GetEmployee() web method accepts an employee id that is to be returned. The code is very similar to what we discussed earlier but this time it fetches only one employee. Note that we have used SqlParameter to represent the passed EmployeeID.

Now you can add Insert(), Update() and Delete() web methods as shown below:

[WebMethod]
public int Insert(string pFirstName, string pLastName)
{
SqlConnection cnn = new SqlConnection(strConn);
cnn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = cnn;
cmd.CommandText = "insert into employees(firstname,lastname)
values (@fname,@lname)";
SqlParameter fname = new SqlParameter("@fname", pFirstName);
SqlParameter lname = new SqlParameter("@lname", pLastName);
cmd.Parameters.Add(fname);
cmd.Parameters.Add(lname);
int i = cmd.ExecuteNonQuery();
cnn.Close();
return i;
}
[WebMethod]
public int Update(int pEmployeeId,string pFirstName, string pLastName)
{
SqlConnection cnn = new SqlConnection(strConn);
cnn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = cnn;
cmd.CommandText = "update employees set firstname=@fname, lastname=@lname where employeeid=@id";
SqlParameter fname = new SqlParameter("@fname", pFirstName);
SqlParameter lname = new SqlParameter("@lname", pLastName);
SqlParameter id = new SqlParameter("@id", pEmployeeId);
cmd.Parameters.Add(fname);
cmd.Parameters.Add(lname);
cmd.Parameters.Add(id);
int i = cmd.ExecuteNonQuery();
cnn.Close();
return i;
}
[WebMethod]
public int Delete(int pEmployeeId)
{
SqlConnection cnn = new SqlConnection(strConn);
cnn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = cnn;
cmd.CommandText = "delete from employees where employeeid=@id";
SqlParameter id = new SqlParameter("@id", pEmployeeId);
cmd.Parameters.Add(id);
int i = cmd.ExecuteNonQuery();
cnn.Close();
return i;
}

The Insert() web method accepts first name and last name of the employee to be added. It then creates an instance of SqlConnection and SqlCommand each and execute the INSERT statement using ExecuteNonQuery() method of SqlCommand object. Similarly, the Update() web method accepts employee id to be updated along with new values for first name and last name and fires an UPDATE statement. Finally, the Delete() web method accepts an employee id that is to be deleted and fires a DELETE statement.

This completes your web service. Uptill this point we have not done anything specific to AJAX functionality. Now it's time to just that. Modify your web service class defination as shown below:

using System.Web.Script.Services;
...
...
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class EmployeeService : System.Web.Services.WebService
{
...
...

Notice the lines marked in bold letters. We have imported a namespace System.Web.Script.Services. This namespace comes from System.Web.Extensions assembly. The [ScriptService] attribute used later is supplied by this namespace. The [ScriptService] attribute enables the web service to be called from the client side JavaScript i.e. ASP.NET AJAX.

That's it! We are now ready to consume our web service from ASP.NET AJAX.

How to consume web service?

In this section we will create a web form that acts as a data entry page for the Employees table by consuming the web service we just created. To being, add a new web form called EmployeeServiceClient.aspx to the web site. Open the toolbox by selecting View > Toolbox menu option. On the toolbox locate a node titled AJAX Extensions. The Figure 2 shows this node.

The AJAX Extensions node displays all the ASP.NET AJAX components that you can use on a web form. Drag and drop a ScriptManager component on the web form. Every web form making use of ASP.NET AJAX needs one ScriptManager component. Open the properties window for the ScriptManager. Locate its Services property and open Service Reference collection editor as shown in Figure 3.

Click on the Add button at the bottom of the dialog and set Path property to the virtual path of the web service i.e. EmployeeService.asmx. Doing so will generate the following markup in the web form file.

<asp:ScriptManager ID="ScriptManager1" runat="server" >
<Services>
<asp:ServiceReference Path="EmployeeService.asmx" />
</Services>
</asp:ScriptManager>

For each web service that you want to consume there must be one <asp:ServiceReference> element inside the <asp:ScriptManager> section. The <asp:ServiceReference> tag registers a web service to use in the current web form.

Now design the web form as shown in Figure 4.

 

The web form consists of a drop down (<SELECT>) that lists all the existing employee IDs. Once you select a specific ID details of that employee are displayed in the two textboxes. You can then update them. In order to add an employee you need to simply enter first name and last name and click on Insert button. Similarly, an employee can be deleted by selecting employee ID in the drop down and clicking on the Delete button. A success or failure message is displayed once the INSERT, UPDATE or DELETE operation is over. The complete markup of the web form is shown below:

<table>
<tr>
<td colspan="2">
<asp:Label ID="Label4" runat="server" Font-Size="X-Large" Text="Employee Management">
</asp:Label></td>
</tr>
<tr>
<td style="width: 100px">
<asp:Label ID="Label1" runat="server" Text="Employee ID :"> </asp:Label></td>
<td style="width: 100px">
<select id="Select1" >
</select>
</td>
</tr>
<tr>
<td style="width: 100px">
<asp:Label ID="Label2" runat="server" Text="First Name :"> </asp:Label></td>
<td style="width: 100px">
<input id="Text1" type="text" /></td>
</tr>
<tr>
<td style="width: 100px">
<asp:Label ID="Label3" runat="server" Text="Last Name :"> </asp:Label></td>
<td style="width: 100px">
<input id="Text2" type="text" /></td>
</tr>
<tr>
<td align="center" colspan="2">
<input id="Button3" type="button" value="Insert" />
<input id="Button4" type="button" value="Update" />
<input id="Button5" type="button" value="Delete" />
</td>
</tr>
<tr>
<td align="center" colspan="2">
<span id="lblMsg" style="font-weight: bold; color: red;"> </span>
</td>
</tr>
</table>

Notice one important thing. We have not used ASP.NET server controls such as DropDownList, TextBox and Button. Instead we have used traditional HTML controls such as <SELECT> and <INPUT>. This is so because we want to call our web service from client side JavaScript and not from server side code. Also, observe that there is a <SPAN> tag at the bottom that will be used for displaying success or failure message.

Next, add a <script> section inside the <head> HTML element. Add a function called CallWebMethod() as shown below:

function CallWebMethod(methodType)
{
switch(methodType)
{
case "select":
EmployeeService.GetEmployees(FillEmployeeList, ErrorHandler,TimeOutHandler);
break;
case "selectone":
var select=document.getElementById("Select1");
var empid=select.options[select.selectedIndex].value;
EmployeeService.GetEmployee(empid,DisplayEmployeeDetails, ErrorHandler,TimeOutHandler);
break;
case "insert":
var text1=document.getElementById("Text1");
var text2=document.getElementById("Text2");
EmployeeService.Insert(text1.value,text2.value,InsertEmployee, ErrorHandler,TimeOutHandler);
break;
case "update":
var select=document.getElementById("Select1");
var empid=select.options[select.selectedIndex].value;
var text1=document.getElementById("Text1");
var text2=document.getElementById("Text2");
var emp=new Employee();
emp.EmployeeID=empid;
emp.FirstName=text1.value;
emp.LastName=text2.value;
EmployeeService.Update(empid,text1.value,text2.value, UpdateEmployee,ErrorHandler,TimeOutHandler);
break;
case "delete":
var select=document.getElementById("Select1");
var empid=select.options[select.selectedIndex].value;
EmployeeService.Delete(empid,DeleteEmployee,ErrorHandler, TimeOutHandler);
break;
}
}

The CallWebMethod() function is a central function that makes calls to the web service. The function accepts a string parameter indicating the method to be called and then calls that method. It contains a switch statement that checks of the method to be called. Each case block calls one web method. Notice how the web method has been called. The ASP.NET AJAX framework automatically creates a JavaScript proxy class for the web serive. The proxy class has the same name as the web service. So, EmployeeService used in the above code is not the actual web service class but a JavaScript proxy class. The proxy contains all the web methods of the original web service. In addition to the original web method parameters, each method can have three extra parameters.

The first extra parameter is a JavaScript function that should be called when the web method call is successfully completed. Remember that any AJAX communication between client and server is anynchronous and hence this function is necessary to capture the return value of web method. The Second parameter is a JavaScript function that is to be called in the event of error. Finally, the thrid extra parameter is a JavaScript function that is to be called if timeout occurs during the web method call.

In the first case ("select") we simply call the GetEmployees() method. In the second case "selectone") we call GetEmployee() method. The employee ID is picked up from the drop down using traditional JavaScript code. Similarly, third, fourth and fifth case blocks call Insert(), Update() and Delete() methods respectively.

In the code shown above we have used five JavaScript functions that are called when the respective web method calls are successful. They are - FillEmployeeList(), DisplayEmployeeDetails(), InsertEmployee(), UpdateEmployee() and DeleteEmployee(). Each of these functions accept a single parameter that represents the return value of the corresponding web method. These functions are discussed next.

function FillEmployeeList(result)
{
var select=document.getElementById("Select1");
for(var i=0;i<result.length;i++)
{
var option=new Option(result[i].EmployeeID,result[i]. EmployeeID);
select.options.add(option);
}
}
   
function DisplayEmployeeDetails(result)
{
var text1=document.getElementById("Text1");
var text2=document.getElementById("Text2");
text1.innerText=result.FirstName;
text2.innerText=result.LastName;
var lblMsg=document.getElementById("lblMsg");
lblMsg.innerText="";
}
   
function InsertEmployee(result)
{
if(result>0)
{
var lblMsg=document.getElementById("lblMsg");
lblMsg.innerText="Employee added successfully!";
}
else
{
var lblMsg=document.getElementById("lblMsg");
lblMsg.innerText="Error occured while adding new employee!";
}
}
function UpdateEmployee(result)
{
if(result>0)
{
var lblMsg=document.getElementById("lblMsg");
lblMsg.innerText="Employee updated successfully!";
}
else
{
var lblMsg=document.getElementById("lblMsg");
lblMsg.innerText="Error occured while updating the employee!";
}
}
function DeleteEmployee(result)
{
if(result>0)
{
var lblMsg=document.getElementById("lblMsg");
lblMsg.innerText="Employee deleted successfully!";
}
else
{
var lblMsg=document.getElementById("lblMsg");
lblMsg.innerText="Error occured while deleting employee!";
}
}

The FillEmployeeList() function receives an array of Employee objects as a parameter. Recollect that our GetEmployees() web method returns an array of Employee objects. It then iterates through the array. With each iteration a new OPTION element is created and added to the drop down (i.e. <SELECT>). The DisplayEmployeeDetails() function receives an Employee object containing details about an employee. It simply displays those details in the two textboxes. The InsertEmployee(), UpdateEmployee() and DeleteEmployee() functions receive an integer indicating the number of records affected by the INSERT, UPDATE and DELETE operation respectively. If the result is greater than zero that indicates success and thy display a success message in the <SPAN> tag. Otherwise they display an error message. When your page is displayed for the first time you need to populate the drop down list with the list of existing employee IDs. This is done by calling CallWebMethod() method in a special function named pageLoad()

function pageLoad()
{
CallWebMethod("select");
}

The pageLoad() function gets called automatically when the web page is loaded in the client browser. Finally, the error handler function and timeout handler function look as shown below:

function TimeOutHandler(result)
{
alert("Timeout :" + result);
}
function ErrorHandler(result)
{
var msg=result.get_exceptionType() + "\r\n";
msg += result.get_message() + "\r\n";
msg += result.get_stackTrace();
alert(msg);
}

The TimeOutHandler() function is called whenever a web method times out. It simply shows an alert to the user. The ErrorHandler() function is called whenever there is any error. The result parameter received by this method provides three methods viz. get_exceptionType(), get_message() and get_stackTrace(). These three methods return the type of exception, detailed error message and stack trace respectively. The ErrorHandler() function simply displays an alert to the end user.

Testing the web page

Now that we have developed the web service and the client application, it's time to test them. Run the web form and try inserting, updating or deleting employees. The Figure 5 shows the web form after updating an employee.

To test the error handler function, deliberately initialize the connection string to empty string and run the web page again. This time you should see an alert as shown below:

Calling External Web Services

In our example the EmployeeService was part of our web site. At times you may need to call web services that are not hosted by your domain at all. ASP.NET AJAX internally relies on XML HTTP object. For security reasons XML HTTP object can not communicate outside the originating web site. That means above technique can not be used for external web services. Unfortunately, ASP.NET AJAX do not have direct solution to this issue (at least in RC release). Microsoft, however, has released a "bridge" technology that is still in CTP stages. Using the bridge you call a wrapper class residing in your web site which in turn calls the actual web service. In current RC release you can create a wrapper web service in your web site which in turn calls the original web service. From the client application you can then call your wrapper web service and achieve the communication. The overall outline of steps is as follows:

  • Add a web reference to the external web service in your web site
  • Create a new web service in your web site
  • Provide wrapper web methods in the newly created web service that call the external web methods via web reference
  • Call this newly added web service from the client application as illustrated in this article

Summary

ASP.NET AJAX provides complete infrastructure to call ASP.NET web services from client side JavaScript. You can easily integrate server data with the user responsive web pages using AJAX. All you need to do is to mark your web service with [ScriptService] attribute. The ASP.NET AJAX framework takes care to generate a JavaScript proxy for your web service. The proxy is then used for calling the web methods.


Bipin Joshi is a software consultant, an author and a yoga mentor having 22+ years of experience in software development. He also conducts online courses in ASP.NET MVC / Core and Design Patterns. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced the Yoga way of life he also teaches Meditation and Mindfulness to interested individuals. To know more about him click here.

Get connected : Twitter  Facebook  Google+  LinkedIn

Posted On : 15 June 2008


Tags : ASP.NET AJAX Web Services WCF Web Forms