65.9K
CodeProject 正在变化。 阅读更多。
Home

支持 AJAX 的分层 Web 应用程序

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.81/5 (6投票s)

2007年4月23日

5分钟阅读

viewsIcon

56800

downloadIcon

324

使用 Microsoft ASP.NET 2.0 构建支持 AJAX 的分层 Web 应用程序

引言

我被我在网上偶然发现的精彩文章深深吸引。Imar Spaanjars 的文章“使用 Microsoft ASP.NET 2.0 构建分层 Web 应用程序”使用 Microsoft ASP.NET 2.0 构建分层 Web 应用程序 帮助我提出了自己的四层 Web 架构,并使用了 Ajax。虽然 Imar 的示例对读者来说很容易理解,但我将 BO(表示层)、BLL(业务逻辑层)和 DAL(数据访问层)扩展为类库项目,并以更结构化的方式封装了整个应用程序。

此应用程序的目的是实现四层架构,并通过单个管理表单演示应用程序的运行。

我们假设有一个名为“ACCOUNTS”的数据库。此数据库包含一个名为“AccountTypes”的表。在下面的示例中,我将演示:

  1. 应用程序如何使用我们自定义的列表集合类(位于 BO 库的 Collection 文件夹内)绑定“Grid View”。
  2. 如何从客户端使用 xmlHTTP 对象执行对“AccountTypes”表的插入和选择操作(AJAX)。
  3. 如何动态构建一个表,使用 XmlHTTP 调用检索到的数组(AJAX)。
  4. 如何通过代码隐藏文件渲染 JavaScript 代码。

Screenshot - MainScreen.gif

背景

我建议您在阅读我的说明之前,先阅读 Imar 的文章。使用 Microsoft ASP.NET 2.0 构建分层 Web 应用程序

使用代码

阶段 I

我将首先创建一个新的类库项目用于业务对象(BO)。

  1. 我将首先创建一个 `AccountTypes.cs` 类。该类将包含该类的所有私有变量以及与数据库字段对应的公共属性。
  2. 在此项目中,我有一个名为“Collections”的单独文件夹用于项目集合。我将创建一个集合类 `AccountTylesList.cs`,它将继承其泛型对应项(List)
  3. 我将保持构造函数代码为空,以便在需要时可以动态填充它。
  4. 您的“BO”项目已准备好进行编译。构建项目将生成 `BO.dll`(保存此库以供将来参考)。

Screenshot - BO.gif

以下是 `AccountTypes` 类的代码

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
    }
}

以下是 `AccountTypesList` 类的代码

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

阶段 II

我现在将创建一个类库项目用于数据访问层(DAL)。

  1. 为此项目添加先前编译的 BO 库的引用,并在所有类中继承“BO”命名空间。
  2. 在 DAL 项目中,我将有一个通用的数据访问文件 `AccessDB.cs`,该文件将由该项目中的所有其他类用于访问 ADO 组件。
  3. 接下来,我为我的 AccountTypes 类(来自 BO)添加一个数据访问层。我将该类命名为 `AccountTypesDB.cs`。
  4. 我将在 `AccountTypesDB.cs` 中包含与 `AccoountTypes.cs`(来自 BO)相关的数据库“选择”、“插入”和“更新”操作。
  5. `AccountTypesDb.cs` 将初始化并设置 `AccountTypes.cs` 中的值,最终这些值将被 `AccountTypesManager.cs`(BLL)使用。
  6. 您的“DAL”项目已准备好进行编译。构建项目将生成 `DAL.dll`(保存此库以供将来参考)。

Screenshot - DAL.gif

以下是 `AccessDB` 类的代码

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

    }

}

以下是 `AccountTypesDb` 类的代码

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,...],,...]

        // 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
    }

}

阶段 III

最后,我将创建一个类库项目用于业务逻辑层(BLL)。

  1. 为此项目添加先前编译的 BO 和 DAL 库的引用,并在所有类中继承“BO”和“DAL”命名空间。
  2. 在这里,我将添加一个 `AccountTypesManager.cs` 类。这里包含在访问数据库之前所需的逻辑、验证和其他计算。
  3. `AccountTypesManager.cs` 类将处理 DLL 和 BO,最终将结果输出到 BO 对象。
  4. 您的“BLL”项目已准备好进行编译。构建项目将生成 `DAL.dll`(保存此库以供将来参考)。

Screenshot - BLL.gif

以下是 `AccountTypesManager` 类的代码

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
    }
}

第四阶段

注意:如果您有兴趣在应用程序中实现 Ajax,则可以跳过第四阶段。第四阶段通过代码隐藏文件展示了基本功能用法。

现在我们的三层架构已准备就绪,我们只需要通过以下方式查看实现和工作原理:

  1. 创建一个新的 Web 项目。
  2. 为该项目添加先前编译的 BO 和 BLL 库的引用,并在所有类中继承“BO”和“BLL”命名空间。请注意,DAL 完全隐藏,除非您将 `DAL.dll` 添加到引用中,否则将无法访问它,这是不必要的。
  3. 在 pageload 中,使用 `AccountTypesManager` 类调用 `GetAccountTypeList` 方法。(请注意,您不必实例化任何类)这将作为您的 grid view 控件“gvAccountTypes”的数据源。
  4. 在代码隐藏文件中的按钮点击事件上,使用 accounttypesmanager 类调用 SaveAccountType 方法。

Screenshot - Flow.gif

以下是 `Page Default.aspx` 的代码

<%@ 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>

以下是 `Class Default.aspx.cs` 的代码

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

第五阶段

我向项目中添加了一个通用的 webservice 文件。我将其命名为 `AjaxAccess.asmx.cs`。

  1. 我添加了一个通用的 `common.cs` 类,用于项目中使用的所有通用函数。
  2. 我在 common 类中创建了一个名为“Script”的类。我更喜欢将脚本代码放在类中,而不是使用 .js 文件。
  3. 脚本类包含用于以下内容的函数:
  4. 渲染通用函数
  5. 渲染 ajax 函数
  6. 在 page load 中,我将通过我的 common 类的 common.script.[methodname] 函数来渲染通用函数和 ajax 函数。
  7. 现在我的应用程序已准备就绪并支持 ajax。我所需要做的就是调用由 (RenderAjaxScript) 渲染的 ajax Get 或 Post 方法。

以下是 `AccountTypes` 类的代码

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();


        }
    }
}

以下是 `Common` 类的代码

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
        }

    }

}

以下是 `AjaxAccess.asmx.cs` 的代码

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 条目

<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>

关注点

在动态检索数据填充表时,我创建了一个二维数组(基本上是一个表示数组结构的字符串),并通过 webservice 将其传输到客户端。到达客户端后,JavaScript 会将其仅解释为字符串而不是数组。我为了找出问题花了很长时间。我在 JavaScript 中发现了一个非常酷的关键字:“eval”。它非常方便。eval 进行了修复。eval() 函数评估一个字符串并将其作为脚本代码执行。

© . All rights reserved.