Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

AJAX Enabled Layered Web Application

1.81/5 (6 votes)
23 Apr 20075 min read 1   308  
Building AJAX Enabled Layered Web Applications with Microsoft ASP.NET 2.0

Introduction

I was really fascinated by the fantastic article I came across on the web. The article "Building Layered Web Applications with Microsoft ASP.NET 2.0" by "Imar Spaanjars" Building Layered Web Applications with Microsoft ASP.NET 2.0 helped me come up with my own four-tier, web-based Architecture using Ajax. While Imar's examples were made easy for the readers, I extended the BO (Presentation), BLL (Business Logic Layer), and the DAL (Data Access Layer) into Class Library projects and wrapped the entire application in a more structured way.

The purpose of this application is to implement the four-tier architecture and demonstrate the running of the application using a single housekeeping form.

Let us assume we have a database named "ACCOUNTS". This database contains a table Named "AccountTypes". In the below examples I will demonstrate:

  1. How the application binds the "Grid View" using our custom List Collection Class (Inside the collection Folder of BO Library).
  2. How the Insert and Select operations to the "AccountTypes" table are carried out from the client side using the xmlHTTP object. (AJAX)
  3. How to dynamically build a table using the array retrieved by the XmlHTTP call. (AJAX)
  4. How to render JavaScript code through code behind files.

Screenshot - MainScreen.gif

Background

I recommend you to go through Imar's Article before going through my illustration. Building Layered Web Applications with Microsoft ASP.NET 2.0

Using the code

Phase I

I will start off by creating a new Class Library Project for the Business Object (BO).

  1. I will first create an AccountTypes.cs class. This will hold all the private variables to the class and public properties that correspond to the database fields.
  2. In this project I have a separate folder called "Collections" for the Item Collections. I'll create a collection class AccountTylesList.cs which will inherit from its generic counterpart (List<accounttypes>)
  3. I'll keep the constructor code empty, so that this can be filled up dynamically when required.
  4. Your "BO" Project is ready for compilation. Building the project will give you BO.dll (Save this Library for future references)

Screenshot - BO.gif

Below is the code for the class AccountTypes:

C#
using System;
using System.Collections.Generic;
using System.Text;
namespace BO
{
    public class AccountTypes
    {
        #region Private Variables
        private string accType = String.Empty;
        private int accTypeId = -1;
        #endregion

        #region Public Properties
        public int AccountTypeId
        {
            get
            {
                return accTypeId;
            }
            set
            {
                accTypeId = value;
            }
        }
        public string AccountType
        {
            get
            {
                return accType;
            }
            set
            {
                accType = value;
            }
        }
        #endregion
    }
}

Below is the code for the class AccountTypesList:

C#
using System;
using System.Collections.Generic;
using System.Text;
namespace BO
{
    public class AccountTypesList : List<AccountTypes>
    {
        public AccountTypesList()
        { }
    }
}

Phase II

I will now create a Class Library Project for the Data Access Layer (DAL).

  1. Add Reference of the previously compiled BO library to this project, and inherit the namespace "BO" in all your classes.
  2. In the DAL project, I'll have a common data access file AccessDB.cs, which will be used by all other classes inside this project to access ADO components.
  3. Next thing I do is add a Data Access Layer for my AccountTypes Class. (From BO). I'll name the Class as AccountTypesDB.cs.
  4. I'll have the database "Select", "Insert" & "Update" operations related to AccoountTypes.cs (From BO) in AccountTypesDB.cs
  5. AccountTypesDb.cs will initialize and set the values in AccountTypes.cs and eventually these values will be consumed by the AccountTypesManager.cs (BLL)
  6. Your "DAL" Project is ready for compilation, Building the project will give you DAL.dll (Save this Library for future references)

Screenshot - DAL.gif

Below is the code for the class AccessDB:

C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;

namespace DAL
{
    class Database
    {
        /// <summary>
        /// Summary description for Database.
        /// </summary>

        #region Private Variables

        private string ConnectionString = string.Empty;
        private SqlConnection oConnection = null;
        private SqlCommand oCommand = null;

        #endregion

        #region Public Methods

        public Database()
        {
            ConnectionString = GetDbConnectionString();

        }
        public static string GetDbConnectionString()
        {
            string DbServer = 
                ConfigurationSettings.AppSettings["DatabaseServer"].ToString();
            string DbName = 
                ConfigurationSettings.AppSettings["Database"].ToString();
            string UserId = 
                ConfigurationSettings.AppSettings["DbUserId"].ToString();
            string Password = 
                ConfigurationSettings.AppSettings["DbPassword"].ToString();
            string ConnectionString = "Data Source=" + DbServer + ";" + 
                "Initial Catalog=" + DbName + ";" + "User ID=" + UserId + ";" + 
                "Password=" + Password;
            return ConnectionString;

        }
        public bool GetDBReader(string SQL, out SqlDataReader SqlDataReader)
        {
            SqlDataReader = null;
            if ((SQL == null) || (SQL == ""))
                return false;
            oConnection = new SqlConnection(ConnectionString);
            oCommand = new SqlCommand(SQL, oConnection);
            oConnection.Open();
            SqlDataReader = 
                oCommand.ExecuteReader(CommandBehavior.CloseConnection);
            return SqlDataReader.HasRows;

        }

        public void DisposeDBReader(SqlDataReader oReader)
        {
            if (oReader != null)
            {
                if (!oReader.IsClosed)
                    oReader.Close();

            }
            if (oCommand != null)
            {
                oCommand.Dispose();

            }
            if (oConnection != null)
            {
                if (oConnection.State != ConnectionState.Closed)
                    oConnection.Close();
                oConnection.Dispose();

            }

        }
        public int ExecuteQuery(string sSQL)
        {
            SqlConnection oConn = new SqlConnection(ConnectionString);
            SqlCommand oComm = new SqlCommand(sSQL, oConn);
            int iRecordsAffected = 0;
            try
            {
                oConn.Open();
                iRecordsAffected = oComm.ExecuteNonQuery();
                oConn.Close();

            }
            catch (Exception ex)
            {
                throw ex;

            }
            finally
            {
                if (oCommand != null)
                {
                    oCommand.Dispose();

                }

                if (oConnection != null)
                {
                    if (oConnection.State != ConnectionState.Closed)
                        oConnection.Close();
                    oConnection.Dispose();

                }

            }
            return iRecordsAffected;

        }
        #endregion

    }

}

Below is the code for the class AccountTypesDb:

C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using BO;

namespace DAL
{
    public class AccountTypesDB
    {
        #region Private Methods
        private static AccountTypes FillDataRecord(IDataRecord myDataRecord)
        {
            AccountTypes accountType = new AccountTypes();
            accountType.AccountTypeId = 
                myDataRecord.GetInt32(
                myDataRecord.GetOrdinal("AccountTypeId"));
            if (!myDataRecord.IsDBNull(myDataRecord.GetOrdinal("AccountType")))
            {
                accountType.AccountType = myDataRecord.GetString(
                    myDataRecord.GetOrdinal("AccountType"));

            }
            return accountType;

        }
        // Function: FillGridData
        // Description: This function is used to create a 2D array to pass data 
        // to the client side
        // Array Format: [[a1,a2,...],<b1,b2,...>,...]
        // return value: AccountTypes Object with the GridData variable set to 
        // the new array value.
        private static AccountTypes FillGridData(SqlDataReader myDataReader)
        {
            AccountTypes accountType = new AccountTypes();
            while (myDataReader.Read())
            {
                if (accountType.GridData == String.Empty || 
                    accountType.GridData.Length == 0)
                {
                    for (int i = 0; i < myDataReader.FieldCount; i++)
                    {
                        if (i == 0)
                            accountType.GridData = "[[" + "\"" + 
                                myDataReader[i].ToString() + "\"";
                        else
                            accountType.GridData = accountType.GridData + ", 
                                \"" + myDataReader[i].ToString() + "\"";

                    }
                    accountType.GridData = accountType.GridData + "]";

                }
                else
                {
                    for (int i = 0; i < myDataReader.FieldCount; i++)
                    {
                        if (i == 0)
                            accountType.GridData = accountType.GridData + ", [" 
                                + "\"" + myDataReader[i].ToString() + "\"";
                        else
                            accountType.GridData = accountType.GridData + ", 
                                \"" + myDataReader[i].ToString() + "\"";
 
                    }
                    accountType.GridData = accountType.GridData + "]";

                }

            }
            if (accountType.GridData != String.Empty || 
                accountType.GridData.Length > 0)
                accountType.GridData = accountType.GridData + "]";

            return accountType;

        }
        #endregion

        #region public Methods
        public static AccountTypes GetAccountType(int accountTypeId)
        {
            string sql = string.Empty;
            AccountTypes accountType = null;
            Database oDatabase = new Database();
            sql = "SELECT * FROM ACCOUNTTYPES WHERE ACCOUNTTYPEID = " + 
                accountTypeId;
            SqlDataReader myReader = null;
            oDatabase.GetDBReader(sql, out myReader);
            if (myReader.Read())
            {
                accountType = FillDataRecord(myReader);

            }
            oDatabase.DisposeDBReader(myReader);
            myReader.Dispose();
            return accountType;

        }
        public static AccountTypes GetGridData(string SQL)
        {
            string sql = string.Empty;
            AccountTypes accountType = null;
            Database oDatabase = new Database();
            sql = SQL;
            SqlDataReader myReader = null;
            oDatabase.GetDBReader(sql, out myReader);
            accountType = FillGridData(myReader);
            oDatabase.DisposeDBReader(myReader);
            myReader.Dispose();
            return accountType;

        }
        public static int SaveAccountType(AccountTypes accounts)
        {
            int result = 0;
            using (SqlConnection myConnection = new 
                SqlConnection(Database.GetDbConnectionString()))
            {
                SqlCommand myCommand = new 
                    SqlCommand("spSaveUpdateAccountType", myConnection);
                myCommand.CommandType = CommandType.StoredProcedure;
                if (accounts.AccountTypeId == -1)
                {
                    myCommand.Parameters.AddWithValue("@accountTypeId", 
                        DBNull.Value);

                }
                else
                {
                    myCommand.Parameters.AddWithValue("@accountTypeId", 
                        accounts.AccountTypeId);

                }
                myCommand.Parameters.AddWithValue("@accountType", 
                    accounts.AccountType);
                SqlParameter returnValue;
                returnValue = myCommand.CreateParameter();
                returnValue.Direction = ParameterDirection.ReturnValue;
                myCommand.Parameters.Add(returnValue);
                myConnection.Open();
                myCommand.ExecuteNonQuery();
                result = Convert.ToInt32(returnValue.Value);
                myConnection.Close();

            }
            return result;

        }
        public static AccountTypesList GetAccountTypeList()
        {
            AccountTypesList tempList = null;
            using (SqlConnection myConnection = new 
                SqlConnection(Database.GetDbConnectionString()))
            {
                SqlCommand myCommand = new SqlCommand("SELECT * FROM 
                    ACCOUNTTYPES", myConnection);
                myCommand.CommandType = CommandType.Text;
                // myCommand.Parameters.AddWithValue("@contactPersonId", 
                // contactPersonId);
                myConnection.Open();
                using (SqlDataReader myReader = myCommand.ExecuteReader())
                {
                    if (myReader.HasRows)
                    {
                        tempList = new AccountTypesList();
                        while (myReader.Read())
                        {
                            tempList.Add(FillDataRecord(myReader));

                        }

                    }
                    myReader.Close();

                }

            }
            return tempList;

        }
        #endregion
    }

}

Phase III

Finally, I will create a Class Library Project for the Business Logic Layer (BLL).

  1. Add Reference of the previously compiled BO & DAL library to this project, and inherit the namespace "BO" & "DAL" in all your classes.
  2. Here, I will add a class AccountTypesManager.cs. Here goes the logic, validations, and other calculations whichever is required before hitting the database.
  3. The AccountTypesManager.cs class will deal with the DLL and BO to finally output the result to the BO object.
  4. Your "BLL" Project is ready for compilation, Building the project will give you DAL.dll (Save this Library for future references)

Screenshot - BLL.gif

Below is the code for the class AccountTypesManager:

C#
using System;
using System.Collections.Generic;
using System.Text;
using BO;
using DAL;

namespace BLL
{
    public class AccountTypesManager
    {
        #region Private Methods
        #endregion

        #region Public Methods
        public static AccountTypes GetAccountType(int accountTypeId)
        {
            return AccountTypesDB.GetAccountType(accountTypeId);

        }
        public static AccountTypes GetGridData(string SQL)
        {
            return AccountTypesDB.GetGridData(SQL);

        }
        public static AccountTypesList GetAccountTypeList()
        {
            return AccountTypesDB.GetAccountTypeList();

        }
        public static int SaveAccountType(AccountTypes accounts)
        {
            ValidateSaveAccountType(accounts);
            accounts.AccountTypeId = AccountTypesDB.SaveAccountType(accounts);
            return accounts.AccountTypeId;

        }

        public static void ValidateSaveAccountType(AccountTypes Accounts)
        {
            if (String.IsNullOrEmpty(Accounts.AccountType))
            {
                throw new Exception("Cannot save an Account Type without a 
                    valid property.");

            }

        }

        public static bool ValidateSaveAccountType(AccountTypes Accounts, 
            bool throwError)
        {
            if (String.IsNullOrEmpty(Accounts.AccountType))
            {
                if (throwError == true)
                    throw new Exception("Cannot save an Account Type without a 
                        valid property.");
                else
                    return false;

            }
            return true;

        }
        #endregion
    }
}

Phase IV

Note: Phase IV can be skipped if you are interested in implementing Ajax in your application. Phase IV shows the basic usage of the functionality through code behind files.

Now that our three-tier architecture is ready, we only have to see the implementation and how things work using the below:

  1. Create a new Web Project.
  2. Add Reference of the previously compiled BO & BLL library to this project, and inherit the namespace "BO" & "BLL" in all your classes. Note that the DAL is completely hidden, and will not be accessible unless you add the DAL.dll to your references which is not required.
  3. In the pageload, call the GetAccountTypeList Method using the AccountTypesManager Class. (Note that you wont have to instantiate any class) This will act as a datasource to your grid view control. "gvAccountTypes"
  4. call the SaveAccountType Method using the accounttypesmanager class on the button click event in the code behind file.

Screenshot - Flow.gif

Below is the code for the Page Default.aspx:

C#
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" 
    Inherits="Accounts._Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Accounts</title>
<script type='text/javascript' language="javascript">
function fnBindGrid()
{
    // The SQL Query used here is only for demonstration purpose. It is not a 
    // good idea to have the SQL queries on the client side.
    PostXmlHttp('AjaxAccess.asmx/WsBindGrid', 'CBBindGrid', 
        'SQL=SELECT * FROM ACCOUNTTYPES');

}
function CBBindGrid()
{
    //State Description 
    //0 The request is not initialized 
    //1 The request has been set up 
    //2 The request has been sent 
    //3 The request is in process 
    //4 The request is complete 
    try
    {
        if (xmlHttp.readyState==4)
        { 
            // The Invisible Div rendered while calling the Ajax Post or Get 
            // method is hidden so that the user can proceed with other clicks.
            document.all.item("HiddenDiv").style.display = "none";
            ParseXml(xmlHttp.responseText);
            if(returnParseXml != null)
            {
                if(Trim(returnParseXml.childNodes[0].nodeValue) == 'Success')
                    alert('Saved Successfully');
                else
                {
                    var myData = [,];
                    myData = eval(returnParseXml.childNodes[0].nodeValue);
                    var htmlTable; 
                    if(myData.length > 0)
                    {
                        var rows = myData.length;
                        var columns = myData[0].length;
                        //loop through the rows
                        htmlTable = '<TABLE>';
                        for( i = 0 ; i < rows ; i++)
                        {
                            htmlTable += '<TR>';
                            //loop through the columns
                            for( j = 0 ; j < columns ; j++ )
                            {
                                htmlTable += '<TD>';
                                htmlTable += myData[i][j];
                                htmlTable += '</TD>';
                                //alert(myData[i][j]);

                            }    
                            htmlTable += '</TR>';    

                        }
                        htmlTable += '</TABLE>';
                        CustTable.innerHTML = htmlTable;

                    }

                }

            }
            else
                alert('Failed: Return XML not found');

        }

    }
    catch(e)
    {
        alert(e.Message);

    }
}

function fnSaveAccountType()
{
    PostXmlHttp('AjaxAccess.asmx/WsSaveAccountType', 'CBSaveAccountType', 
        'AccountType='+Trim(document.all.item("txtAccountType").value));

}

function CBSaveAccountType()
{
    //State Description 
    //0 The request is not initialized 
    //1 The request has been set up 
    //2 The request has been sent 
    //3 The request is in process 
    //4 The request is complete 
    try
    {
        if (xmlHttp.readyState==4)
        { 
            // The Invisible Div rendered while calling the Ajax Post or Get 
            // method is hidden so that the user can proceed with other clicks.
            document.all.item("HiddenDiv").style.display = "none";
            ParseXml(xmlHttp.responseText);

            if(returnParseXml != null)
            {
                if(Trim(returnParseXml.childNodes[0].nodeValue) == 'Success')
                {
                    alert('Saved Successfully');
                    fnBindGrid();

                }
                else
                    alert(returnParseXml.childNodes[0].nodeValue);

            }
            else
                alert('Failed: Return XML not found');

        }

    }
    catch(e)
    {
        alert(e.Message);

    }

}        
</script>    
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:GridView ID="gvAccountTypes" runat="server"></asp:GridView>
            <div id='CustTable'></div>
            <input id="txtAccountType" type="text" />
            <input id="Button1" type="button" value="Save" 
                onclick="fnSaveAccountType()" />
        </div>
    </form>
</body>
</html>

Below is the code for the Class Default.aspx.cs:

C#
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using BO;
using BLL;

namespace Accounts
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            //Common.Script.RenderCommonScript(Page, "CommonScript");
            //Common.Script.RenderAjaxScript(Page,"AjaxScript");
            gvAccountTypes.DataSource = 
                AccountTypesManager.GetAccountTypeList();
            gvAccountTypes.DataBind();

        }

    }

}

Screenshot - Accounts.gif

Phase V

I added a common webservice file to the project. I name this as AjaxAccess.asmx.cs

  1. I added a common class common.cs, for all the common functions to be used in my project.
  2. I made a class "Script" insided the common class. I prefer putting the script code insided a class, rather than having a .js file.
  3. the script class contains methods for:
  4. rendering the common functions
  5. rendering the ajax functions
  6. On the page load, I will render the common functions and ajax functions through the common.script.[methodname] functions of my common class.
  7. Now my application is ready and ajax enabled. All I need to do is call the ajax Get or Post methods rendered by (RenderAjaxScript).

Below is the code for the class AccountTypes:

C#
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using BO;
using BLL;

namespace Accounts
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Common.Script.RenderCommonScript(Page, "CommonScript");
            Common.Script.RenderAjaxScript(Page,"AjaxScript");
            //Binding data using our custom list class from codebehind.
            //gvAccountTypes.DataSource = 
            //    AccountTypesManager.GetAccountTypeList();
            //gvAccountTypes.DataBind();

        }
    }
}

Below is the code for the class Common:

C#
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

namespace Accounts
{
    public class Common
    {
        public Common()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        public class Script
        {
            public Script()
            {
            }
            #region Render Common Script
            public static void RenderCommonScript(System.Web.UI.Page oPage, 
                string ScriptName)
            {
                oPage.RegisterStartupScript(ScriptName, @"
        <script type='text/javascript' language="'javascript'">
        function Trim(StringValue)
        {
            try
            {
                if (StringValue == null)
                    return '';
                //Remove leading spaces, tabs and carriage 
                                //returns
                while ((StringValue.substring(0, 1) == ' ') || 
                                    (StringValue.substring(0, 1) == '\n') || 
                                    (StringValue.substring(0, 1) == '\t') || 
                                    (StringValue.substring(0, 1) == '\r'))
                {
                    StringValue = StringValue.substring(1, 
                                            StringValue.length);
                }                
                //Remove trailing spaces, tabs and carriage 
                                //returns
                while ((StringValue.substring(
                                    StringValue.length-1, 
                                    StringValue.length) == ' ') || 
                                    (StringValue.substring(
                                    StringValue.length-1, 
                                    StringValue.length) == 
                                    '\n') || (StringValue.substring(
                                    StringValue.length-1, StringValue.length) 
                                    == '\t') || (StringValue.substring(
                                    StringValue.length-1, 
                                    StringValue.length) == '\r'))
                {
                    StringValue = StringValue.substring(0, 
                                            StringValue.length-1);
                }

            }
            catch(e)
            {
                alert('Error Occured while Triming the 
                                    String:\n' + e.message);
            }
            return StringValue;

        }
        </script>");


            }
            # endregion
            #region Render AJAX SCRIPT
            public static void RenderAjaxScript(System.Web.UI.Page oPage, 
                string ScriptName)
            {
                string renderAjaxScript = string.Empty;
                renderAjaxScript = @"
        // This is an Invisible Div Rendered on the page in order to 
                // avoid user input while the page is busy retriving data.
        // This will be shown and hidden on the page consecutively as 
                // and when required.
        <div id='HiddenDiv' style='DISPLAY: none; LEFT: 0px; 
                  POSITION: absolute; TOP: 0px; WIDTH=100%; HEIGHT=100%'>
                <table align='center' width='100%' height='100%' 
                      cellpadding='0' cellspacing='0'>
                <tr>
              <td width='100%' height='100%' align='center' 
                            valign='middle'><IMG alt='' src='";
              // The PreLoaderImage tag in the webconfig holds the 
                          // Physical path of the preloader image.
              // The loading image is usually displayed while the 
                          // webservice is busy retriving the data from the 
                          // database.
              renderAjaxScript = renderAjaxScript + 
                              ConfigurationSettings.AppSettings[
                              "PreLoaderImage"].ToString();
              renderAjaxScript = renderAjaxScript + @"'>
              </td>
               </tr>
           </table>
        </div>";
        oPage.Response.Write(renderAjaxScript);
        oPage.RegisterStartupScript(ScriptName, @"
        <script type='text/javascript' language="'javascript'">
            var xmlHttp;    
            function PostXmlHttp(URL, CallBackFunction, Parameters)
            {  
                xmlHttp=null;
                try
                {   // Firefox, Opera 8.0+, Safari    
                    xmlHttp=new XMLHttpRequest(); 
                    
                }
                catch (e)
                {   // Internet Explorer    
                    try
                    {      
                        xmlHttp=new 
                                                   ActiveXObject(
                                                   'Msxml2.XMLHTTP'); 
                
                    }
                    catch (e)
                    {      
                        try
                        {        
                            xmlHttp=new 
                                                            ActiveXObject(
                                                          'Microsoft.XMLHTTP');
                
                        }
                        catch (e)
                        {        
                            alert('Your browser 
                                                            does not support 
                                                            AJAX!');
                            return;     
            
                        }      

                    }    
            
                }
                try
                {
                    if (xmlHttp!=null)
                    {
                        xmlHttp.onreadystatechange = 
                                                    eval(CallBackFunction);
            
                    }
                    if(document.all.item('HiddenDiv'))
                    {
                        // The Invisible Div appears on 
                                                // the user screen to avoid 
                                                // extra clicks by the user.
                        
                                               document.all.item(
                                               'HiddenDiv').style.display = '';
            
                    }                
                    xmlHttp.open('POST',URL,true);
                    xmlHttp.setRequestHeader(
                                        'Content-Type',  
                                        'application/x-www-form-urlencoded; 
                                        charset=UTF-8');
                    xmlHttp.send(Parameters);
                
                }
                catch(e)
                {
                    alert('Error Occured while Posting 
                                            XmlHttp Values:\n' + e.message);
            
                }
            }
            function GetXmlHttp(URL, CallBackFunction, Parameters)
            {  
                xmlHttp=null;
                try
                {   // Firefox, Opera 8.0+, Safari    
                    xmlHttp=new XMLHttpRequest();
            
                }
                catch (e)
                {   // Internet Explorer    
                    try
                    {      
                        xmlHttp=new ActiveXObject(
                                                    'Msxml2.XMLHTTP');
            
                    }
                    catch (e)
                    {      
                        try
                        {        
                            xmlHttp=new 
                                                          ActiveXObject(
                                                          'Microsoft.XMLHTTP'); 

                        }
                        catch (e)
                        {        
                            alert('Your browser 
                                                        does not support 
                                                        AJAX!');
                            return;

                        }

                    }    

                }    
                try
                {
                    if (xmlHttp!=null)
                    {
                        xmlHttp.onreadystatechange = 
                                                    eval(CallBackFunction);

                    }
                    if(document.all.item('HiddenDiv'))
                    {
                        // The Invisible Div appears on 
                                                // the user screen to avoid 
                                                // extra clicks by the user.
                        
                                               document.all.item(
                                               'HiddenDiv').style.display = '';

                    }                
                    xmlHttp.open('POST',URL,true);
                    xmlHttp.send(null);

                }
                catch(e)
                {
                    alert('Error Occured while Getting 
                                            XmlHttp Values:\n' + e.message);
            
                }

            }
            var returnParseXml
            function ParseXml(text)
            {
                // code for IE
                if (window.ActiveXObject)
                {
                    var doc=new 
                                            ActiveXObject('Microsoft.XMLDOM');
                    doc.async='false';
                    doc.loadXML(text);
            
                }
                // code for Mozilla, Firefox, Opera, etc.
                else
                {
                    var parser=new DOMParser();
                    var doc=parser.parseFromString(
                                            text,'text/xml');

                }// documentElement always represents the root 
                                 // node
                returnParseXml = doc.documentElement;

            }

        </script>");

            }
            # endregion
        }

    }

}

Below is the code for AjaxAccess.asmx.cs:

C#
using System;
using System.Data;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.ComponentModel;
using BLL;
using BO;

namespace Accounts
{
    /// <summary>
    /// Summary description for AjaxAccess
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ToolboxItem(false)]
    public class AjaxAccess : System.Web.Services.WebService
    {

        [WebMethod]
        public string WsSaveAccountType(string AccountType)
        {
            try
            {
                AccountTypes oAccountTypes = new AccountTypes();
                oAccountTypes.AccountType = AccountType;
                AccountTypesManager.SaveAccountType(oAccountTypes);
                return "Success";

            }
            catch (Exception ex)
            {
                return "Failed: " + ex.Message;

            }
        }

        [WebMethod]
        public string WsBindGrid(string SQL)
        {
            try
            {
                return AccountTypesManager.GetGridData(SQL).GridData;

            }
            catch (Exception ex)
            {
                return "Failed: " + ex.Message;

            }

        }

    }

}

Web Config Entries

ASP.NET
<appSettings>
  <add key="DatabaseServer" value="(local)" />
  <add key="Database" value="ACCOUNTS" />
  <add key="DbUserId" value="sa" />
  <add key="DbPassword" value="sa" />
  <add key="PreLoaderImage" value="Images/loading.gif" />
</appSettings>

Points of Interest

While retriving data to fill up the table dynamically, I was creating a two dimensional array (basically, its a string representing the array structure) and transporting it to the client side using a webservice. Upon reaching the client side, JavaScript would interpret this as only string and not array. I went crazy trying to find the problem. I found this really cool key word in JavaScript: "eval". Very Handy to use. eval did the trick for me. The eval() function evaluates a string and executes it as if it was script code.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here