Saturday, 6 August 2011

Calling server method from client side using HttpHandler


There are various ways to call server methods from Client Side in ASP.NET such as XML HTTP AJAX, Web Services, ICallbackHandler, IHttpHanlder etc. Previously I blogged some post related to calling server methods from Client Side. This post also concentrates on implementing the same example but using IHttpHanlder.

The requirement in the implementation is to create a user creation entry screen. The user can enter the User Id, Name and Email id and Save the details in the database.

  1. When the user types the User Id and get the focus out from the text box, the system should automatically call a server method (using IHttpHanlder method) to verify the User Id already exist in the database or not.
  2. If the User Id already exists, the system should show message to inform the user that the User Id is Not Available for register otherwise Available.
  3. When the call made to the server, there should not be any post back on the page.

I have an XML file (UserDetails.xml) which stores the user details. The xml markup looks like –
<?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>
Added a GenericHanlder (UserInfoHandler.ashx) file in the project and updated the code for verifying User Id exists in the XML file or not.
/// <summary>
/// This is the method will be executed when the handler called. 
/// </summary>
/// <param name="context"></param>
public void ProcessRequest(HttpContext context)
{
    context.Response.ContentType = "text/plain";
    try
    {
        // Sleep statement is for testing Processing image on the screen
        System.Threading.Thread.Sleep(1500);

        // Getting input parameter
        string strUserId = context.Request.Form["UserId"].ToUpper();

        #region Code to open the XML file and verify with the user id
        string strFileName = HttpContext.Current.Request.PhysicalApplicationPath + @"Data\UserDetails.xml";

        XPathDocument doc = new XPathDocument(strFileName);
        XPathNavigator nav = doc.CreateNavigator();
        XPathNodeIterator iterator;

        iterator = nav.Select(@"//User[UserID='" + strUserId + "']");
        
        bool IsFound = false;

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

            if (nav2.Select(@"//Users").Current.SelectSingleNode("UserID").InnerXml.Length > 0)
                IsFound = true;
            break;
        }
        #endregion

        context.Response.Write(IsFound.ToString());
    }
    catch (Exception ex)
    {
        context.Response.Write("error");
    }
}
If you look at the code, the line #7 specifies the output of this handler is a plan text and line #37 writes the result of the existence (whether true or false) as a response. Incase if any error occurred, it will write error as a response.

In this function I have used line #11 to pause the process for some time to delay the response. It is used for showing the process image in the UI. All other code is as usual to fetch the XML file and verify the User Id.

The below code shows the UI script for managing user entries
<table>
    <tr>
        <td>User Id</td>
        <td>
            <asp:TextBox ID="txtUserId" runat="server" Width="120px" CssClass="TextStyle" style="float:left;"></asp:TextBox><span id="spanAvailableStatus" style='display:none'></span><img id='spanProcessing' alt='' src= "Images/ajax-loader.gif" style='display:none;float:left;padding-top:7px;padding-left:5px' />
        </td>
    </tr>
    <tr>
        <td>First Name</td>
        <td><asp:TextBox ID="txtFirstName" runat="server" Width="200px" CssClass="TextStyle"></asp:TextBox></td>
    </tr>
    <tr>
        <td>Last Name</td>
        <td><asp:TextBox ID="txtLastName" runat="server" Width="200px" CssClass="TextStyle"></asp:TextBox></td>
    </tr>
    <tr>
        <td>Mail Id</td>
        <td><asp:TextBox ID="txtMailId" runat="server" Width="200px" CssClass="TextStyle"></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>
I use JQuery in this example to call the handler. So to test this example is sure to include JQuery script file.
<script src="Scripts/jquery-1.6.2.min.js" type="text/javascript"></script>
<script src="Scripts/Script.js" type="text/javascript"></script>
Below function shows how to call the handler from JQuery and once the response comes from handler how to use it.
$(function() {
    $("#txtUserId").blur(function() {
        $("#spanAvailableStatus").css("display", "none");
        $("#spanProcessing").css("display", "block");
        jQuery.post('UserInfoHandler.ashx',
                        { UserId: $("#txtUserId").val() },
                        function(data) {
                            if (data == "True") {
                                $("#spanAvailableStatus").html("Not Available");
                                $("#spanAvailableStatus").addClass("Red");
                            }
                            else {
                                $("#spanAvailableStatus").html("Available");
                                $("#spanAvailableStatus").addClass("Green");
                            }
                            $("#spanAvailableStatus").css("display", "block");
                            $("#spanProcessing").css("display", "none");
                        }
                   );
    })
})
In this code, line #5 calls the Generic Handler using post method. The post method has three parameters as defined below.
  1. Specifies the handler file. Here is the generic handler file required to call in post method. Line #5
  2. Pass the values to the handler using query string. Line #6
  3. Define inline function (or call function) to handle the response. line #7

Http Handler is same as using XML Http Ajax. The handler will work as normal as we use coding in an aspx.cs file.

In handler we have one entry point which is ProcessRequest method. If there is a requirement to call the same handler for more than one places and calling from the Javascript with multiple query string values how to handle it in the code.

The below code shows an example of getting query string values and process according to that.
public void ProcessRequest(HttpContext context)
{
    if (context.Request.QueryString["type"] == "Request1")
    {
        context.Response.Write("Response for Request1");
    }
    else if (context.Request.QueryString["type"] == "Request2")
    {
        context.Response.Write("Response for Request2");
    }
    else
    {
        context.Response.Write("Response for Others");
    }
}
Below code used to save the user details on click of Save button.
protected void btnSave_Click(object sender, EventArgs e)
{
    try
    {
        string strFileName = HttpContext.Current.Request.PhysicalApplicationPath + @"Data\UserDetails.xml";

        if (!File.Exists(strFileName))
        {
            XmlTextWriter textWritter = new XmlTextWriter(strFileName, null);
            textWritter.WriteStartDocument();
            textWritter.WriteStartElement("Users");
            textWritter.WriteEndElement();
            textWritter.Close();
        }

        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load(strFileName);

        XmlElement subRoot = xmlDoc.CreateElement("User");

        subRoot.AppendChild(CreateXMLElement(xmlDoc, "UserID", txtUserId.Text.Trim().ToUpper()));
        xmlDoc.DocumentElement.AppendChild(subRoot);

        subRoot.AppendChild(CreateXMLElement(xmlDoc, "FirstName", txtFirstName.Text.Trim()));
        xmlDoc.DocumentElement.AppendChild(subRoot);

        subRoot.AppendChild(CreateXMLElement(xmlDoc, "LastName", txtLastName.Text.Trim()));
        xmlDoc.DocumentElement.AppendChild(subRoot);

        subRoot.AppendChild(CreateXMLElement(xmlDoc, "MailId", txtMailId.Text.Trim()));
        xmlDoc.DocumentElement.AppendChild(subRoot);

        subRoot.AppendChild(CreateXMLElement(xmlDoc, "IsLocked", "1"));
        xmlDoc.DocumentElement.AppendChild(subRoot);

        xmlDoc.Save(strFileName);

        txtUserId.Text = "";
        txtFirstName.Text = "";
        txtLastName.Text = "";
        txtMailId.Text = "";
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

public XmlElement CreateXMLElement(XmlDocument xmlDoc, string name, string value)
{
    XmlElement xmlElement = xmlDoc.CreateElement(name);
    XmlText xmlText = xmlDoc.CreateTextNode(value);
    xmlElement.AppendChild(xmlText);
    return xmlElement;
}
Note: This function is used to save the user details, so once a user added and if we try again with the same user Id it will show Not Available. This function is a normal event and not use any AJAX call.

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

The screen layout will be as below


4 Responses to “Calling server method from client side using HttpHandler”

  • Krishna says:
    19 March 2012 at 09:10

    Excellent, exactly what I was looking for. Thanks

  • Thiru says:
    19 March 2012 at 10:10

    Nice... Thanks dude..

  • Anonymous says:
    11 September 2013 at 02:18

    Can you pls show some implementations for 4.5 Aysnchronous http hanlder

  • Thirumalai M says:
    12 September 2013 at 01:59

    Hi. Currently I am bit busy, I will work on this when I get time. Thanks.

Post a Comment