Wednesday 11 May 2011

How to implement XML HTTP AJAX in ASP.NET Web Pages


In lots of time having post back for a simple functionality will take the application to make the user feel bad. In those situations using AJAX concept will drastically help to increase the user experience in the applications. This post concentrates on calling server code from the client side using XML HTTP AJAX.

Before going on implementation let us understand some basic working concept of XML HTTP AJAX.

Introduction: What is AJAX?

Asynchronous JavaScript and XML is abbreviated as AJAX, which is used to create a rich user interface. Normally in our ASP.NET page, if we click a button there will be a post back to the server. It will execute a sequence of event including that button event handler. Once the code is executed the response will sent to the client machine in the form of HTML.

Once the client got the response from the server, it will refresh the entire page by replacing the new HTML content. As for each and every event the page doing post back and refreshing the full page, the user may feel bad in experience and has to wait lot of time for a simple functionality.

The AJAX overcomes this issue by generating and replacing a part of the page which required on demand. For example, I am having a Grid which shows list of products and an entry form for entering the values in the same screen. When I add a new product from entry form, the values must be added to the grid after it saved in the database. When I select a particular product from the grid, the same product information must be fetched from the database and show to the entry form. In this scenario, I can make Grid and Entry form as a separate portion and render / refresh a particular portion from the server when I required.

In AJAX, the pages are been divided in to multiple portions and rendered from the server by portion when required and there is no post back in the application. So it will be much faster than traditional ASP.NET application. Another important benefit is you can call multiple calls to the server at a same time by asynchronous method call and when the client receives response from the client; it will replace the related portion (you can even make call in synchronously if required). So the user interface will be like a windows application. That is the beauty of AJAX.

There are various methods to implement AJAX in an ASP.NET page such as XML HTTP method, ASP.NET Extension etc. In this post; I wish to explain how XML HTTP can be used to achieve AJAX implementation.

But most of the time, the beginners who starts to use Javascript might feel tedious for doing communication between Server and Client by holding values in client and transferring to server, calling server method from client etc.,.

How XML HTTP AJAX works:

In normal XML HTTP AJAX implementation there will be two web pages. In that one page will act as the caller which is the page required the data for processing and another one is a remote page accessible thru a URI which will generate the response to caller. A simple example of this concept is show in the below figure.


To understand with an example I am going to take a scenario of creating User in an application.

In some of the websites, we have seen in the user creation module when user enters login Id there will be a message Available or Not available based on the user details already stored in the database and these messages will show to the user by not refreshing the whole page. Mostly those functionalities are done with AJAX concepts.

In this example, I am using XML to store user details as it is only for demonstrating AJAX concept and not for database operations.

The implementation as follows:

The XML which hold the User Details.
<?xml version="1.0" encoding="utf-8"?>
<Users>
  <User>
    <UserID>A-C71970F</UserID>
    <FirstName>Aria</FirstName>
    <LastName>Cruz</LastName>
    <MailId>Aria.Cruz@gmail.com</MailId>
    <IsLocked>1</IsLocked>
  </User>
  <User>
    <UserID>A-R89858F</UserID>
    <FirstName>Annette</FirstName>
    <LastName>Roulet</LastName>
    <MailId>Annette.Roulet@gmail.com</MailId>
    <IsLocked>1</IsLocked>
  </User>
</Users>

The HTML script of calling page which defines the User entry interface
<div>
    <table>
        <tr>
            <td>User Id</td>
            <td>
                <asp:TextBox ID="txtUserId" runat="server" Width="120px" onchange="UserNameCheck(this.id)"></asp:TextBox><span id="spanAvailableStatus"></span>
            </td>
        </tr>
        <tr>
            <td>First Name</td>
            <td><asp:TextBox ID="txtFirstName" runat="server" Width="200px"></asp:TextBox></td>
        </tr>
        <tr>
            <td>Last Name</td>
            <td><asp:TextBox ID="txtLastName" runat="server" Width="200px"></asp:TextBox></td>
        </tr>
        <tr>
            <td>Mail Id</td>
            <td><asp:TextBox ID="txtMailId" runat="server" Width="200px"></asp:TextBox></td>
        </tr>
        <tr>
            <td colspan="2" style="text-align:center">
                <asp:Button ID="btnSave" Text="Save" Width="60px" runat="server" 
                    onclick="btnSave_Click" />
                <asp:Button ID="btnClear" Text="Clear" Width="60px" runat="server" />
            </td>
        </tr>
    </table>
</div>

This is the Javascript which calls remote page GenerateAJAXResult.aspx with some query string. HandleResponse() is the function which handle the response comes from remote page.
var is_ie = (navigator.userAgent.indexOf('MSIE') >= 0) ? 1 : 0;
var is_ie5 = (navigator.appVersion.indexOf("MSIE 5.5") != -1) ? 1 : 0;
var xmlHttp;

/* This function requests the HTTPRequest, will be used to render the Dynamic content html markup 
* and it will call HandleResponse to handle the response
*/
function UserNameCheck(id) {
    var url = 'GenerateAJAXResult.aspx?UserID=' + document.getElementById(id).value;
    xmlHttp = createAjaxObject();
    if (xmlHttp) {
        xmlHttp.open('get', url, true);
        xmlHttp.onreadystatechange = HandleResponse;
        xmlHttp.send(null);
    }
}
/* This function is used to handler the http response */
function HandleResponse() {
    // If Response completed
    if (xmlHttp.readyState == 4) {

        // Here is the response
        var str = xmlHttp.responseText;
        if (str == 'True') {
            document.getElementById('spanAvailableStatus').innerHTML = 'Not Available';
            document.getElementById('spanAvailableStatus').className = 'Red';
        }
        else {
            document.getElementById('spanAvailableStatus').innerHTML = 'Available';
            document.getElementById('spanAvailableStatus').className = 'Green';
        }
        
        xmlHttp.abort();
    }
}
/* function to create Ajax object */
function createAjaxObject() {
    var ro;
    var browser = navigator.appName;
    if (browser == "Microsoft Internet Explorer") {
        if (xmlHttp != null) {
            xmlHttp.abort();
        }
        ro = new ActiveXObject("Microsoft.XMLHTTP");
    }
    else {
        if (xmlHttp != null) {
            xmlHttp.abort();
        }
        ro = new XMLHttpRequest();
    }
    return ro;
}

/* Get the XML Http Object */
function GetXmlHttpObject(handler) {
    var objXmlHttp = null;
    if (is_ie) {
        var strObjName = (is_ie5) ? 'Microsoft.XMLHTTP' : 'Msxml2.XMLHTTP';

        try {
            objXmlHttp = new ActiveXObject(strObjName);
            objXmlHttp.onreadystatechange = handler;
        }
        catch (e) {
            alert('Object could not be created');
            return;
        }
    }
    return objXmlHttp;
}

function xmlHttp_Get(xmlhttp, url) {
    xmlhttp.open('GET', url, true);
    xmlhttp.send(null);
}

The remote page (GenerateAJAXResult.aspx) code behind, which generate the response.
protected void Page_Load(object sender, EventArgs e)
{
    // Checking Customer Id exist in the database or not
    bool IsCustomerExist = IsUserIdExist(Request["UserID"].ToString().ToUpper());

    Response.Clear();
    Response.ContentType = "text/xml";
    Response.Write(IsCustomerExist.ToString());
    Response.End();
}
/// <summary>
/// Method will load the XML and findout is the user exist or not
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public bool IsUserIdExist(string userId)
{
    try
    {
        // Sleep statement is for testing Processing image on the screen
        System.Threading.Thread.Sleep(1500);

        string strFileName = HttpContext.Current.Request.PhysicalApplicationPath + @"Data\UserDetails.xml";

        if (File.Exists(strFileName))
        {
            XPathDocument doc = new XPathDocument(strFileName);
            XPathNavigator nav = doc.CreateNavigator();
            XPathNodeIterator iterator;

            iterator = nav.Select(@"//User[UserID='" + userId + "']");

            while (iterator.MoveNext())
            {
                XPathNavigator nav2 = iterator.Current.Clone();

                if (nav2.Select(@"//Users").Current.SelectSingleNode("UserID").InnerXml.Length > 0)
                    return true;
            }
        }
        return false;
    }
    catch (Exception ex)
    {
        throw ex;
    }
}
'VB Code behind
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        ' Checking Customer Id exist in the database or not
        Dim IsCustomerExist As Boolean = IsUserIdExist(Request("UserID").ToString().ToUpper())

        Response.Clear()
        Response.ContentType = "text/xml"
        Response.Write(IsCustomerExist.ToString())
        Response.[End]()
    End Sub
    ''' <summary>
    ''' Method will load the XML and findout is the user exist or not
    ''' </summary>
    ''' <param name="userId"></param>
    ''' <returns></returns>
    Public Function IsUserIdExist(ByVal userId As String) As Boolean
        Try
            ' Sleep statement is for testing Processing image on the screen
            System.Threading.Thread.Sleep(1500)

            Dim strFileName As String = HttpContext.Current.Request.PhysicalApplicationPath + "Data\UserDetails.xml"

            If File.Exists(strFileName) Then
                Dim doc As New XPathDocument(strFileName)
                Dim nav As XPathNavigator = doc.CreateNavigator()
                Dim iterator As XPathNodeIterator

                iterator = nav.[Select]("//User[UserID='" & userId & "']")

                While iterator.MoveNext()
                    Dim nav2 As XPathNavigator = iterator.Current.Clone()

                    If nav2.[Select]("//Users").Current.SelectSingleNode("UserID").InnerXml.Length > 0 Then
                        Return True
                    End If
                End While
            End If
            Return False
        Catch ex As Exception
            Throw ex
        End Try
    End Function

Just to add one more functionality, We can make the code to show a processing image to let the user know something is on the process in code when request sent to the server and waiting for response. Below is the modified javascript code on HandleResponse function where some code added (highlight) to show up the image.
/* This function is used to handler the http response */
function HandleResponse() {
    // If Response completed
    if (xmlHttp.readyState == 4) {
        
        // Here is the response
        var str = xmlHttp.responseText;
        if (str == 'True') {
            document.getElementById('spanAvailableStatus').innerHTML = 'Not Available';
            document.getElementById('spanAvailableStatus').className = 'Red';
        }
        else {
            document.getElementById('spanAvailableStatus').innerHTML = 'Available';
            document.getElementById('spanAvailableStatus').className = 'Green';
        }
        document.getElementById('spanAvailableStatus').style.display = "block";
        document.getElementById('spanProcessing').style.display = "none";
        
        xmlHttp.abort();
    }
    else {
        document.getElementById('spanAvailableStatus').style.display = "none";
        document.getElementById('spanProcessing').style.display = "block";
    }
}

This code has been tested with IE 6.0/9.0, Firefox 3.6, Opera 11.01

You can see the output in video here



download the working example of the source code in C# here and in VB here

2 Responses to “How to implement XML HTTP AJAX in ASP.NET Web Pages”

  • Anonymous says:
    3 September 2013 at 16:07

    This is an excellent article. I have downloaded the code. It works nicely. But how i can prevent to save data when User Id already exists ? Would you please focus on this issue?

  • Thirumalai M says:
    3 September 2013 at 18:34

    In the HandleResponse() function, you can add code to disable the Save button and show a text message (or alert message) when user id created.

    function HandleResponse() {
    // If Response completed
    if (xmlHttp.readyState == 4) {

    // Here is the response
    var str = xmlHttp.responseText;
    if (str == 'True') {
    document.getElementById('spanAvailableStatus').innerHTML = 'Not Available';
    document.getElementById('spanAvailableStatus').className = 'Red';
    alert('The User Id already created, you can't save the record')
    document.getElementById('btnSave').disabled = true;
    }
    else {
    document.getElementById('spanAvailableStatus').innerHTML = 'Available';
    document.getElementById('spanAvailableStatus').className = 'Green';
    document.getElementById('btnSave').disabled = false;
    }

    xmlHttp.abort();
    }
    }

Post a Comment