使用jQuery AJAX和ASP.NET与您的数据库进行许多方式进行通信

我最近通过使用jQuery完成了一系列通过AJAX调用数据库的一系列文章。在几乎所有文章中,我使用Web服务作为我的数据访问机制。从一些文章所吸引的评论中判断,这导致了一点混乱。但Web服务只是一种机制。页面方法和简单的aspx文件有两个。最后,正如评论者所指出的那样,Benny Halperin,ASHX文件是另一种选择。在本文中,我将审查这些方法中的每一种。

每个示例都将具有相同的要求,并且是为了获取和显示与从名为Customer.aspx的页面上的DropdownList中选择的特定CustomerID相关的NorthWind客户详细信息。

Customer.aspx的裸露骨骼如下:



<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Customer.aspx.cs" Inherits="Customer" %>

<!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="服务器">
    <title>Untitled Page</title>

</head>
<body>
    <form id="form1" runat="服务器">
    <div id="SelectCustomers">
      <asp:DropDownList ID="Customers" runat="服务器">
      </asp:DropDownList>
    </div>
    <div id="CustomerDetails">
    </div>
    </form>
</body>
</html>

这具有一个代码背后,其中获得数据并绑定到DropdownList以提供客户列表:


using
System; using System.Data.SqlClient; public partial class Customer : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { string connect = "Server=MyServer;Database=Northwind;Trusted_Connection=True"; string query = "SELECT CustomerID, CompanyName FROM Customers"; using (SqlConnection conn = new SqlConnection(connect)) { using (SqlCommand cmd = new SqlCommand(query, conn)) { conn.Open(); Customers.DataSource = cmd.ExecuteReader(); Customers.DataValueField = "CustomerID"; Customers.DataTextField = "CompanyName"; Customers.DataBind(); } } } }

aspx文件

我会开始说这不是你可能经常看到的。但是,我提到了它 使用Ajax和ASP.NET的我的第一个文章之一。 ASPX页面不做任何与数据库通信,并准备HTML作为对调用代码的响应。该页面称为fetchcustomer.aspx,并且我选择了使用代码后面的选项。这与代码一起如下所示:



<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<script runat="服务器">
  protected void Page_Load(object sender, EventArgs e)
  {
    string connect = "Server=MIKE;Database=Northwind;Trusted_Connection=True";
    string query = "SELECT CompanyName, Address, City, Region, PostalCode," + 
              "Country, Phone, Fax FROM Customers WHERE CustomerID = @CustomerID";
    string id = Request.QueryString["CustomerID"];
    if (id != null && id.Length == 5)
    {
      using (SqlConnection conn = new SqlConnection(connect))
      {
        using (SqlCommand cmd = new SqlCommand(query, conn))
        {
          cmd.Parameters.AddWithValue("CustomerID", Request.QueryString["CustomerID"]);
          conn.Open();
          SqlDataReader rdr = cmd.ExecuteReader();
          if (rdr.HasRows)
          {
            while (rdr.Read())
            {
              Response.Write("<p>");
              Response.Write("<strong>" + rdr["CompanyName"].ToString() + "</strong><br />");
              Response.Write(rdr["Address"].ToString() + "<br />");
              Response.Write(rdr["City"].ToString() + "<br />");
              Response.Write(rdr["Region"].ToString() + "<br />");
              Response.Write(rdr["PostalCode"].ToString() + "<br />");
              Response.Write(rdr["Country"].ToString() + "<br />");
              Response.Write("Phone: " + rdr["Phone"].ToString() + "<br />");
              Response.Write("Fax: " + rdr["Fax"].ToString() + "</p>");
            }
          }
        }
      }
    }
    else 
    {
      Response.Write("<p>No customer selected</p>"); 
    }
    Response.End();
  }
</script>

此文件仅负责生成对AJAX呼叫的响应,并且不必使用UI本身,因此不需要使用代码页面。这就是该文件利用的原因<script runat="server">。它将值传递到CustomerID QueryString值中并获取相关的客户详细信息,然后通过DataReader中返回的字段,并响应.WML中的响应。jQuery有许多方法请求此页面并处理响应。看的第一种方式是 加载() 函数,从远程文件加载HTML:

<script type="text/javascript" src="script/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
  $(document).ready(function() {
    $('#Customers').change(function() {
      $('#CustomerDetails').load("FetchCustomer.aspx?CustomerID=" + $('#Customers').val());
    });
  });

</script>

上面的代码将进入Customer.aspx的头部部分。首先,引用最新版本的jQuery库,然后作为页面加载 - $(文件).ready() - 将函数应用于下拉列表的Onchange事件。此功能只需使用CustomerDetail的ID获取div以加载从fetchcustomer.aspx返回的HTML,并通过查询字符串中当前所选的下拉列表值。

替代方案 加载() $ .get() 。这完全相同,除了回调参数指定与Ajax请求的响应要完成的内容。只需用以下内容替换Customer.aspx文件头上的JavaScript代码:

<script type="text/javascript" src="script/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
  $(document).ready(function() {
    $('#Customers').change(function() {
      $.get("FetchCustomer.aspx",
        { CustomerID: "" + $('#Customers').val() + "" },
        function(data) {
          $('#CustomerDetails').html(data);
        });
    });
  });
</script>

这里,QueryString值与{}括号中的QueryString名称一起传递,其中名称和由冒号分隔的值。 jQuery采用这些值并将QueryString构造为HTTP请求的一部分,以便称为页面是 fetchcustomer.aspx?customerid = somevalue。有趣的是要注意这一点,如果你将{}括号传递到 加载 方法,您将强制HTTP发布请求,而不是GET请求。在里面 $.get() 示例,响应在变量中可用 数据 和 the jQuery html() 函数用于将其放在CustomerDetails div中。

我将查看的最终调用方法是我在以前的文章中使用的是那个: $ .ajax() 。这是一个更具功能丰富的方法,因为它允许应用一系列选项来管理不同类型的呼叫和错误处理。因此,它可以(并且有 - 如果以前的评论是任何事情,请毫无疑问。尽管如此,我们将在当前要求调用ASPX文件的上下文中查看它:

<script type="text/javascript" src="script/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
  $(document).ready(function() {
    $('#Customers').change(function() {
      $.ajax({
        contentType: "text/html; charset=utf-8",
        data: "CustomerID=" + $('#Customers').val(),
        url: "FetchCustomer.aspx",
        dataType: "html",
        success: function(data) {
          $("#CustomerDetails").html(data);
        }
      });
    });
  });
</script>

在前面的代码中仅应用了有限数量的选项,但它已经清楚地看到了 加载() $ .get() 替代方案更简单使用。我们将使用它 加载() 选择下一个方法,ASHX文件。

ASHX文件

ASHX文件是将部分内容提供给网页的方便方法。它们实际上是httphandlers,并负责处理传入的HTTP请求并提供适当的响应。通常,它们用于提供二进制内容,例如图像或存储在数据库中或Web应用程序文件系统之外的文件。要将少量的HTML插入网页上的特定位置,它们可能非常有用。选择添加新项目 - >通用处理程序,您应该为从IhttpPhandler继承的类中获取模板。它将包含一个方法 - processRequest()和一个属性 - isReusable()。渲染输出的逻辑将进入processRequest(),如下所示:

<%@ WebHandler Language="C#" Class="FetchCustomer" %>

using System;
using System.Web;
using System.Data;
using System.Data.SqlClient;

public class FetchCustomer : IHttpHandler {
    
    public void ProcessRequest (HttpContext context) {
        context.Response.ContentType = "text/html";
        string connect = "Server=MIKE;Database=Northwind;Trusted_Connection=True";
        string query = "SELECT CompanyName, Address, City, Region, PostalCode," +
                  "Country, Phone, Fax FROM Customers WHERE CustomerID = @CustomerID";
        string id = context.Request.QueryString["CustomerID"];
        if (id != null && id.Length == 5)
        {
          using (SqlConnection conn = new SqlConnection(connect))
          {
            using (SqlCommand cmd = new SqlCommand(query, conn))
            {
              cmd.Parameters.AddWithValue("CustomerID", context.Request.QueryString["CustomerID"]);
              conn.Open();
              SqlDataReader rdr = cmd.ExecuteReader();
              if (rdr.HasRows)
              {
                while (rdr.Read())
                {
                  context.Response.Write("<p>");
                  context.Response.Write("<strong>" + rdr["CompanyName"].ToString() + "</strong><br />");
                  context.Response.Write(rdr["Address"].ToString() + "<br />");
                  context.Response.Write(rdr["City"].ToString() + "<br />");
                  context.Response.Write(rdr["Region"].ToString() + "<br />");
                  context.Response.Write(rdr["PostalCode"].ToString() + "<br />");
                  context.Response.Write(rdr["Country"].ToString() + "<br />");
                  context.Response.Write("Phone: " + rdr["Phone"].ToString() + "<br />");
                  context.Response.Write("Fax: " + rdr["Fax"].ToString() + "</p>");
                }
              }
            }
          }
        }
        else
        {
          context.Response.Write("<p>No customer selected</p>");
        }
        context.Response.End();
    }
 
    public bool IsReusable {
        get {
            return false;
        }
    }
}

该方法几乎没有与ASPX文件方法不同,除非Endpoint IT引用除外,jQuery Load()方法也是相同的:

<script type="text/javascript" src="script/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
  $(document).ready(function() {
    $('#Customers').change(function() {
      $('#CustomerDetails').load("FetchCustomer.ashx?CustomerID=" + $('#Customers').val());
    });
  });
</script>

页面方法

页面方法是属于其页面类的静态方法。因此,它可以放在一个<script runat="server">块,或在代码后面。由于我已经在Customer.aspx中使用了代码填充了PageLoad()上的DropdownList来填充DropdownList,我将坚持使用代码的方法。如果请求ContentType设置为应用程序/ JSON,则ASP.NET 3.5方法将始终序列化并返回在另一个内部包装的JSON对象:D。

要将方法添加到后面的代码,需要两个其他引用:

using System.Text;
using System.Web.Services;

这些将允许我使用StringBuilder对象构建返回值,并使用[WebMethod]属性来装饰页面方法。完整方法如下:

[WebMethod]
public static string FetchCustomer(string CustomerID)
{
  string response = "<p>No customer selected</p>";
  string connect = "Server=MyServer;Database=Northwind;Trusted_Connection=True";
  string query = "SELECT CompanyName, Address, City, Region, PostalCode," +
            "Country, Phone, Fax FROM Customers WHERE CustomerID = @CustomerID";
  if (CustomerID != null && CustomerID.Length == 5)
  {
    StringBuilder sb = new StringBuilder();
    using (SqlConnection conn = new SqlConnection(connect))
    {
      using (SqlCommand cmd = new SqlCommand(query, conn))
      {
        cmd.Parameters.AddWithValue("CustomerID", CustomerID);
        conn.Open();
        SqlDataReader rdr = cmd.ExecuteReader();
        if (rdr.HasRows)
        {
          while (rdr.Read())
          {
            sb.Append("<p>");
            sb.Append("<strong>" + rdr["CompanyName"].ToString() + "</strong><br />");
            sb.Append(rdr["Address"].ToString() + "<br />");
            sb.Append(rdr["City"].ToString() + "<br />");
            sb.Append(rdr["Region"].ToString() + "<br />");
            sb.Append(rdr["PostalCode"].ToString() + "<br />");
            sb.Append(rdr["Country"].ToString() + "<br />");
            sb.Append("Phone: " + rdr["Phone"].ToString() + "<br />");
            sb.Append("Fax: " + rdr["Fax"].ToString() + "</p>");
            response = sb.ToString();
          }
        }
      }
    }
  }
  return response;
}

它或多或少与ASPX版本相同。 jQuery代码也是:

<script type="text/javascript" src="script/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
  $(document).ready(function() {
    $('#Customers').change(function() {
    $.ajax({
        type: "POST",
        contentType: "application/json; charset=utf-8",
        data: "{ CustomerID: '" + $('#Customers').val() + "'}",
        url: "Customer.aspx/FetchCustomer",
        dataType: "json",
        success: function(data) {
          $("#CustomerDetails").html(data.d);
        }
      });
    });
  });
</script>

从此伪Web服务获得的响应是​​序列化JSON对象:

{"d":"\u003cp\u003e\u003cstrong\u003eQUICK-Stop\u003c/strong\u003e\u003cbr /
\u003eTaucherstraße 10\u003cbr /\u003eCunewalde\u003cbr /\u003e\u003cbr /
\u003e01307\u003cbr /\u003eGermany\u003cbr /\u003ePhone: 0372-035188
\u003cbr /\u003eFax: \u003c/p\u003e"}

Unicode转义字符显示代替非ASCII字符 - 主要是"<" (\u003c) and ">"(\ U003E)标记字符。如您所见,从该方法返回的HTML表示为单个属性的值:D。返回部分HTML的替代方法是返回自定义业务对象。这就是我们接下来的看法。在客户页面类中,我将定义公司对象的属性:

public class Company
{
  public string CompanyID { get; set; }
  public string CompanyName { get; set; }
  public string Address { get; set; }
  public string City { get; set; }
  public string Region { get; set; }
  public string PostalCode { get; set; }
  public string Country { get; set; }
  public string Phone { get; set; }
  public string Fax { get; set; }
}

这是后跟修订的页面方法,返回公司对象,从DataReader填充:

[WebMethod]
public static Company FetchCustomer(string CustomerID)
{
  Company c = new Company();
  string connect = "Server=MyServer;Database=Northwind;Trusted_Connection=True";
  string query = "SELECT CompanyName, Address, City, Region, PostalCode," +
            "Country, Phone, Fax FROM Customers WHERE CustomerID = @CustomerID";
  if (CustomerID != null && CustomerID.Length == 5)
  {
    using (SqlConnection conn = new SqlConnection(connect))
    {
      using (SqlCommand cmd = new SqlCommand(query, conn))
      {
        cmd.Parameters.AddWithValue("CustomerID", CustomerID);
        conn.Open();
        SqlDataReader rdr = cmd.ExecuteReader();
        if (rdr.HasRows)
        {
          while (rdr.Read())
          {
            c.CompanyName = rdr["CompanyName"].ToString();
            c.Address = rdr["Address"].ToString();
            c.City = rdr["City"].ToString();
            c.Region = rdr["Region"].ToString();
            c.PostalCode = rdr["PostalCode"].ToString();
            c.Country = rdr["Country"].ToString();
            c.Phone = rdr["Phone"].ToString();
            c.Fax = rdr["Fax"].ToString();
          }
        }
      }
    }
  }
  return c;
}

此调用的结果是对象d再次,其中有一个属性 - 类型公司的另一个对象:

{"d":{"__type":"Company","CompanyID":null,"CompanyName":"Old World Delicatessen",
"Address":"2743 Bering St.","City":"Anchorage","Region":"AK","PostalCode":"99508",
"Country":"USA","Phone":"(907) 555-7584","Fax":"(907) 555-2880"}}

由于我们不再返回HTML,因此我们必须解析嵌套对象并在客户端脚本中创建HTML:

<script type="text/javascript" src="script/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
  $(document).ready(function() {
    $('#Customers').change(function() {
      $.ajax({
        type: "POST",
        contentType: "application/json; charset=utf-8",
        data: "{ CustomerID: '" + $('#Customers').val() + "'}",
        url: "Customer.aspx/FetchCustomer",
        dataType: "json",
        success: function(data) {
          var Company = data.d;
            $('#CustomerDetails').append
              ('<p><strong>' + Company.CompanyName + "</strong><br />" +
              Company.Address + "<br />" +
              Company.City+ "<br />" +
              Company.Region + "<br />" +
              Company.PostalCode + "<br />" +
              Company.Country + "<br />" +
              Company.Phone + "<br />" +
              Company.Fax + "</p>" )
        }
      });
    });
  });
</script>

ASP.NET Web服务

我已经详细说明了如何使用jQuery使用ASP.NET 3.5 Web服务 本文但是对于完整性,我们将通过向项目添加新项目来创建一个:

在刚刚创建的文件中,我们添加了一种方法。这是完整的代码:

<%@ WebService Language="C#" Class="FetchCustomer" %>

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Data.SqlClient;
using System.Text;
using System.Web.Script.Services;


[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
[ScriptService]


public class FetchCustomer : WebService
{
  [WebMethod]
  public string GetCustomer(string CustomerID)
  {
    string response = "<p>No customer selected</p>";
    string connect = "Server=MyServer;Database=Northwind;Trusted_Connection=True";
    string query = "SELECT CompanyName, Address, City, Region, PostalCode," +
              "Country, Phone, Fax FROM Customers WHERE CustomerID = @CustomerID";
    if (CustomerID != null && CustomerID.Length == 5)
    {
      StringBuilder sb = new StringBuilder();
      using (SqlConnection conn = new SqlConnection(connect))
      {
        using (SqlCommand cmd = new SqlCommand(query, conn))
        {
          cmd.Parameters.AddWithValue("CustomerID", CustomerID);
          conn.Open();
          SqlDataReader rdr = cmd.ExecuteReader();
          if (rdr.HasRows)
          {
            while (rdr.Read())
            {
              sb.Append("<p>");
              sb.Append("<strong>" + rdr["CompanyName"].ToString() + "</strong><br />");
              sb.Append(rdr["Address"].ToString() + "<br />");
              sb.Append(rdr["City"].ToString() + "<br />");
              sb.Append(rdr["Region"].ToString() + "<br />");
              sb.Append(rdr["PostalCode"].ToString() + "<br />");
              sb.Append(rdr["Country"].ToString() + "<br />");
              sb.Append("Phone: " + rdr["Phone"].ToString() + "<br />");
              sb.Append("Fax: " + rdr["Fax"].ToString() + "</p>");
              response = sb.ToString();
            }
          }
        }
      }
    }
    return response;
  }
}

此方法将返回以前使用的部分HTML,但要注意的要点是[ScriptService]属性已经取消了解,这允许JavaScript调用该方法,并且该方法不是静态的(就像它必须是使用页面方法)。 jQuery代码与页面方法方法几乎相同:

  

<script type="text/javascript" src="script/jquery-1.3.2.min.js"></script>
  <script type="text/javascript">
    $(document).ready(function() {
      $('#Customers').change(function() {
        $.ajax({
          type: "POST",
          contentType: "application/json; charset=utf-8",
          url: "FetchCustomer.asmx/GetCustomer",
          data: "{ CustomerID: '" + $('#Customers').val() + "'}",
          dataType: "json",
          success: function(data) {
            $("#CustomerDetails").html(data.d);
          }
        });
      });
    });
</script>

概括

我们已经看到了许多方法来在ASP.NET中执行数据访问,使用JQuery Ajax:ASPX文件,ASHX文件,页面方法和Web服务,其中选择如何调用ASPX文件。那么你应该使用哪个?

ASPX文件方法是来自来自其他技术(如经典ASP或PHP)的开发人员最熟悉的方法。它还提供更容易的访问或较短的代码以及负载()方法。虽然未显示在此,但您也可以将自定义业务对象序列化为JSON,并使用 getjson() jQuery的方法。这有助于保持关注的分离。要进一步帮助,没有理由在单独的文件夹中不能将aspx文件分组。您的应用程序中的所有页面将可以访问它们。最后一点支持ASPX方法是您可以使用内联编码方法返回HTML,而不是使用response.write()来呈现输出。这对来自其他技术迁移的人来说,这将是最熟悉的。

ASHX文件很好,整洁。它们比ASPX文件更轻,因此它们不会导致在Web服务器上实例化整个页面类。但是,就像aspx文件一样,每个人只能负责一种方法。如果您想要重载的方法,则每个都需要在自己的单独文件中。

如果您不介意使用演示文稿逻辑混合数据访问,则页面方法很棒,或者希望用2层保持苗条的下行方法。理想情况下,它们应该放在将使用该方法的同一页面中,而不是如果可能需要多页。这样可能会导致混淆。

当您希望允许其他应用程序使用您的数据访问服务时,全Web服务最有用。它们也是在您的应用程序中清除不同功能的很好的方法,或者如果您对ASPX文件方法厌恶。最后,Web服务允许多种相关方法驻留在同一位置,使逻辑分组和维护更容易。