This article is Part 2 in a 3 part series on AJAX for beginners. In this part, you will see how to use XMLHttpRequest and jQuery AJAX to implement a cascading Dropdown.
There are three articles in this mini series:
Introduction
This article discusses the ways in which ASP.NET applications can implement asynchronous functionality, i.e., AJAX by using XMLHttpRequest
object and jQuery AJAX.
Background
In Part 1 of this series, we have seen various ways an ASP.NET developer can implement the AJAX functionality in the web applications. We have also seen how to use the ASP.NET AJAX server controls. Now the focus of this article will be on using XMLHttpReuqest
object and jQuery AJAX to implement the asynchronous behavior in the web applications.
XMLHttpObject
facilitates the exchange of data between client and server behind the scenes, i.e., the partial page update is possible using the XMLHttpObject
.
jQuery is a JavaScript framework which makes a lot of client side work easy for the developers. jQuery AJAX is a set of routines that provides behind the scenes communication between client and server thus facilitating partial page updates.
Using the Code
In this article, we will try to work on a very common problem faced by many developers. We will try to implement the cascading dropdown lists using AJAX. We will implement this first using the XMLHttpObject
and then by jQuery AJAX.
Before starting with the problem at hand, let us understand the solution and the desired functionality. Let us say we have a database keeping a list of all the continents and countries. The user will be presented with two dropdown lists. First dropdown will contain a list of continents and when user selects any continent from this list, the second dropdown list should be updated asynchronously, i.e., without causing any postback.
Let us look at the Database table containing the list of continents and countries and the containing data.
Note: The database has not been optimized or normalized in any way because that was not the focus of this article.
Now we have a helper class that takes care of all the database communications. This class ideally should be present as a separate solution for Data Access layer but for the sake of simplicity, I have created this class.
public class DBHelper
{
public static DataTable GetContinentList()
{
DataTable result = null;
try
{
using (SqlConnection con = new SqlConnection(
ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
using (SqlCommand cmd = con.CreateCommand())
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select distinct continentName from Countries";
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
result = new DataTable();
da.Fill(result);
}
}
}
}
catch (Exception)
{
}
return result;
}
public static DataTable GetCountriesList(string continentNmame)
{
DataTable result = null;
try
{
using (SqlConnection con = new SqlConnection(
ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
using (SqlCommand cmd = con.CreateCommand())
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select countryName from Countries
where continentName = @continent";
cmd.Parameters.Add(new SqlParameter("@continent", continentNmame));
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
result = new DataTable();
da.Fill(result);
}
}
}
}
catch (Exception)
{
}
return result;
}
}
This class will help in retrieving the list of continents and list of countries specific to that continent. Let us now start working on the real problem.
Using XMLHttpObject
Let us create a page with two drop down lists (default.aspx). We will initialize the first dropdown list with first continent name and the second dropdown list with the countries of that continent. We will then use XMLHttpObject
to change the contents of second dropdown list based on user selection of first dropdown. The code behind of this page will contain the logic for page_load
only.
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
drpContinent.DataSource = DBHelper.GetContinentList();
drpContinent.DataTextField = "continentName";
drpContinent.DataValueField = "continentName";
drpContinent.DataBind();
drpCountry.DataSource = DBHelper.GetCountriesList(drpContinent.SelectedValue);
drpCountry.DataTextField = "countryName";
drpCountry.DataValueField = "countryName";
drpCountry.DataBind();
}
}
Now, the next thing we want to do is to handle the onchange
event of the first dropdown on client side.
<asp:DropDownList ID="drpContinent" runat="server" onchange="UpdateCountries();">
</asp:DropDownList>
Now to use XMLHttpObject
to get the list of countries based on user selection, we need to do the following:
- Create the
XmlHttpObject
. - Retrieve the current user selection of first dropdown.
- Pass this value to a web page on server as query string using
XMLHttpObject
. - Handle the response of this async request we just made.
- Retrieve the values in the response.
- Change the second dropdown lists items as per the new values found in response.
The important thing to note in the above algorithm is that we need a page that can handle this asynchronous request, extract the query string and then push the results to the response. Let us create a page called frmForAjaxCalls.aspx for this purpose and implement the functionality.
public partial class frmForAjaxCalls : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string continentName = Request.QueryString["cont"] as string;
if (continentName != null)
{
DataTable table = DBHelper.GetCountriesList(continentName.Trim());
string result = string.Empty;
foreach (DataRow r in table.Rows)
{
result += r["countryName"].ToString() + ";";
}
Response.Clear();
Response.Write(result);
Response.End();
}
}
}
Now the only thing remaining is the client side JavaScript code that will call this page using XMLHttpObject
. The following code will show how it is done.
var xmlHttp;
function UpdateCountries()
{
xmlHttp = null;
if(window.XMLHttpRequest)
{
xmlHttp = new XMLHttpRequest();
}
else if(window.ActiveXObject)
{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
if(xmlHttp != null)
{
var contName = document.getElementById('<%=drpContinent.ClientID %>').value;
xmlHttp.onreadystatechange=state_Change;
xmlHttp.open("GET","frmForAjaxCalls.aspx?cont="+contName,true);
xmlHttp.send(null);
}
}
function state_Change()
{
if (xmlHttp.readyState==4)
{
if (xmlHttp.status==200)
{
var countries = xmlHttp.responseText.split(';');
var length = countries.length;
document.getElementById('<%=drpCountry.ClientID %>').options.length = 0;
var dropDown = document.getElementById('<%=drpCountry.ClientID %>');
for(var i = 0; i < length - 1; ++i)
{
var option = document.createElement("option");
option.text = countries[i];
option.value = countries[i];
dropDown.options.add(option);
}
}
}
}
Now when we run this page, we can see that the selection on first dropdown list will trigger the async communication with the server and the second dropdown list will be populated with the values of countries in that continent. All this was done without having any postback to the server.
Using jQuery AJAX
Let us create a similar page with two dropdown lists (default2.aspx). We will initialize the first dropdown list with first continent name and second dropdown list with the countries of that continent. We will then use jQuery AJAX to change the contents of second dropdown list based on user selection of first dropdown. The code behind of this page will contain the logic for page_load
.
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
drpContinent.DataSource = DBHelper.GetContinentList();
drpContinent.DataTextField = "continentName";
drpContinent.DataValueField = "continentName";
drpContinent.DataBind();
drpCountry.DataSource = DBHelper.GetCountriesList(drpContinent.SelectedValue);
drpCountry.DataTextField = "countryName";
drpCountry.DataValueField = "countryName";
drpCountry.DataBind();
}
}
Now unlike XMLHttpObject
, if we are using jQuery
, we don't have to create another page to handle the async request. What we can do is have a static
function in the asme page (or we could create a separate page if we want to) that will take some arguments and return some value. Passing the argument to this function, invoking this function and handling the result will be the jQuery's responsibility on the client side. Let us look at this function:
[System.Web.Services.WebMethod]
public static string OnContinentChange(string continentName)
{
DataTable table = DBHelper.GetCountriesList(continentName.Trim());
string result = string.Empty;
foreach (DataRow r in table.Rows)
{
result += r["countryName"].ToString() + ";";
}
return result;
}
This static
function should also be decorated with an attribute WebMethod
. This indicates that this method will be called from client side.
Note: This static
method with WebMethod
attribute can be thought of as the small web service that can be accessed from client side using this page's URL.
Now to use jQuery AJAX to get the list of countries based on user selection, we need to do the following:
- Handle the
onchange
event of the first dropdown. - Retrieve the current user selection of first dropdown
- Create a
JSON
object for passing this data to the server. - Specify the page/method name to be called.
- Handle the response callback.
- Retrieve the values in the response.
- Change the second dropdownlists items as per the new values found in response.
The following code will show how it is done using jQuery:
$(document).ready(function() {
$("#drpContinent").change(function() {
$.ajax( {
type: "POST",
url: "Default2.aspx/OnContinentChange",
data: "{'continentName':'"+$('#drpContinent').val() +"'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
var countries = msg.split(';');
var length = countries.length;
document.getElementById('<%=drpCountry.ClientID %>').options.length = 0;
var dropDown = document.getElementById('<%=drpCountry.ClientID %>');
for(var i = 0; i < length - 1; ++i) {
var option = document.createElement("option");
option.text = countries[i];
option.value = countries[i];
dropDown.options.add(option);
}
}
});
});
});
Now when we run this page, we can see that the selection on first dropdown list will trigger the async communication with the server and the second dropdown list will be populated with the values of countries in that continent. All this was done without having any postback to the server.
Points of Interest
We have seen two ways in which we can implement AJAX behavior in an ASP.NET website. First method was using XMLHttpObject
and second one is using the jQuery AJAX. We have had only a cursory look at these two ways to understand how things can be done. There are lot of options related to both these approaches that can be customized to have better control over the asynchronous communication. I suggest we read about these two approaches in detail. It will really help in better understanding of things.
We also solved a very common problem that developers (new) face and that is creating cascading dropdown lists. This article presents two ways of doing that. We can also use AJAX controls toolkit to achieve this and many more AJAX functionalities. But perhaps, that deserves a separate discussion.
History
- 12th June, 2012: First version