Skip to content

Latest commit

 

History

History
2292 lines (1793 loc) · 90.8 KB

File metadata and controls

2292 lines (1793 loc) · 90.8 KB

七、使用 jQuery Ajax

本章演示如何使用 jQuery 通过 Ajax 发布异步请求。 所涵盖的食谱清单如下:

  • 用 ASP 建立 Ajax。 使用 jQuery 净
  • 使用页面的方法
  • 消费 Web 服务
  • 使用 WCF 服务
  • 从 Web API 检索数据
  • 对控制器操作进行 Ajax 调用
  • 对 HTTP 处理程序进行 Ajax 调用

简介

AJAX(异步 JavaScript 和 XML)是 Adaptive Path 的 Jesse James Garrett 创造的一个术语。 它代表不同技术的组合,帮助您与服务器无缝通信,而不需要刷新页面。 Ajax 应用涉及以下技术:

  • 用于运行核心 Ajax 引擎的 JavaScript
  • 对象来与服务器通信
  • 使用 HTML 和 CSS 或 XSLT 的 web 演示
  • DOM 来处理 HTML 结构
  • 用于数据交换的 XML 和 JSON

XmlHttpRequest对象用于向服务器发送 HTTP/HTTPS 请求。 大多数现代浏览器都有一个内置的XmlHttpRequest对象。

注意事项

JSON(JavaScript 对象表示法)是一种轻量级的数据交换格式,越来越多地用于 Ajax 应用。 它基本上是一个名称/值对的集合,可以用于不同的数据类型,如字符串、数字、布尔值、数组和对象。

在一个典型的 web 应用中,客户端将数据提交给服务器进行处理,服务器将刷新后的内容返回给客户端。 这将导致可见的页面刷新,并且用户需要等待页面重新加载后才能与页面进行进一步的交互。 这个请求/响应流程如下图所示:

Introduction

Ajax 为浏览器和服务器之间的通信提供了一种新的范例。 使用 Ajax,可以更新网页的部分内容,而无需将整个页面发送到服务器。 通过在幕后进行通信,无需显式页面刷新。 用户可以继续使用网页,而不必等待服务器的响应,如下图所示:

Introduction

在基于 Ajax 的应用中,对 Ajax 引擎进行 JavaScript 调用,该引擎使用XmlHttpRequest对象将请求异步发送到服务器。 因此,后端通信变得透明,并且用户与应用的交互不会中断。 这增强了页面的交互性; 从而改善用户的体验。 同时,提高了页面的性能和速度。

jQuery 库提供了许多使用 Ajax 的方法。 在本章中,我们将探讨使用以下方法:

  • $.ajaxSetup(options):此方法可用于定义在页面上进行 Ajax 调用的默认设置。 设置一次完成,页面上的所有后续 Ajax 调用都使用这些默认设置。
  • $.ajax(settings):这是一个通用的低级函数,可以帮助您创建任何类型的 Ajax 请求。 有很多配置设置,可以使用这个函数应用如 HTTP 请求的类型(GET/POST/PUT/DELETE),请求 URL,参数被发送到服务器,数据类型的响应,以及要执行的回调函数的成功/失败的调用 Ajax 调用。
  • $("…").load():这是一个快捷方法,用于从服务器加载文本或 HTML 内容,并将其显示在匹配的元素中。
  • $.getJSON():该方法向服务器发送 HTTPGET请求。 数据以 JSON 格式返回。

注意事项

从服务器接收到的响应的数据类型可以是文本、HTML、XML、JSON 或 JSONP。 在底层,快捷方法使用$.ajax()方法向服务器发送请求。

用 ASP 建立 Ajax。 使用 jQuery 净

这个配方演示了如何使用$.ajaxSetup()函数来配置全局设置,以便在 web 页面上进行 Ajax 调用。 这些设置将在多个 Ajax 调用中使用。 下表总结了本例中使用的结构:

|

构造

|

类型

|

描述

| | --- | --- | --- | | $("#identifier") | jQuery 选择器 | 这将根据元素的 ID 选择一个元素 | | $.ajax() | jQuery 函数 | 这将向服务器发送一个带有设置选项的 Ajax 请求。 | | $.ajaxSetup() | jQuery 函数 | 这将为 Ajax 请求设置默认值。 | | .append() | jQuery 方法 | 这将在每个匹配元素的末尾插入内容。 | | click | jQuery 的事件 | 当您单击一个元素时,它就会触发。 它对应于 JavaScript 的click事件。 | | .each() | jQuery 方法 | 这将遍历匹配的元素,并为每个元素执行一个函数。 | | event.preventDefault() | jQuery 方法 | 这将防止触发事件的默认动作。 | | .find() | jQuery 方法 | 这将查找与筛选器匹配的所有元素。 | | .html() | jQuery 方法 | 这将返回第一个匹配元素的 HTML 内容,或者设置每个匹配元素的 HTML 内容。 | | .load() | jQuery 方法 | 这会从服务器加载文本或 HTML 数据,并将其显示在匹配的元素中。 | | .on() | jQuery 事件绑定 | 这将一个或多个事件的事件处理程序附加到匹配的元素。 | | .text() | jQuery 方法 | 这会返回每个匹配元素的的组合文本内容,或者设置每个匹配元素的文本内容。 |

准备

按照下面的步骤来使用 ASP 设置 Ajax.NET 使用 jQuery:

  1. Let's create a web page that triggers Ajax calls to retrieve the HTML and XML data, respectively. On loading, the page will display a Button control, as shown in the following screenshot:

    Getting ready

    点击Button控件后,页面将从各个来源检索内容,并以以下格式显示在页面上:

    Getting ready

  2. 为了创建此页面,启动一个ASP.NET Web 应用项目在 Visual Studio 中使用模板,并将其命名为Recipe1(或其他合适的名称)。

  3. 将 jQuery 库添加到项目中Scripts文件夹中。

  4. 添加一个 web 表单到项目中,并在表单中包含 jQuery 库。

  5. 接下来,我们将创建一个包含一些测试数据的 HTML 文件。 要做到这一点,右键单击Solution Explorer选项卡中的项目,然后转到Add|New Item。 从对话框中的Installed templates部分,转到Web|HTML Page。 将该文件命名为Sample.html。 添加以下内容到这个 HTML 文件:

  6. 通过在Solution Explorer选项卡中右键单击项目,并导航到Add|New Item,将一个 XML 文件添加到项目。 在弹出的对话框中,从“Installed templates”中选择“Data|XML File”。 将文件命名为Sample.xml,文件中包含以下内容:

    <?xml version="1.0" encoding="utf-8" ?>
    <BookShelf>
      <Book>
        <Title>Huckleberry Finn</Title>
        <Author>Mark Twain</Author>
        <Category>Classic</Category>
      </Book>
      <Book>
        <Title>David Copperfield</Title>
        <Author>Charles Dickens</Author>
        <Category>Classic</Category>
      </Book>
      <Book>
        <Title>The Alchemist</Title>
        <Author>Paulo Coelho</Author>
        <Category>Fiction</Category>
      </Book>
      <Book>
        <Title>You Can Win</Title>
        <Author>Shiv Khera</Author>
        <Category>Non-Fiction</Category>
      </Book>
    </BookShelf>
    
  7. 向表单添加一个Button控件以及两个空的div元素:一个用于显示 HTML 内容,另一个用于显示 XML 内容。 因此,表单的标记如下:

    <asp:Button ID="btnLoad" runat="server" Text="Click to load content using AJAX" />
    <div id="htmlcontent">
    </div>
    <div id="xmlcontent">
    </div>
    
  8. 要样式化从 HTML 和 XML 文件中检索的内容,请向head元素添加以下样式:

怎么做……

在页面的script块中包含以下 jQuery 代码:

script type="text/javascript">
  $(document).ready(function() {
    $.ajaxSetup({
      method: "GET",
      data: {},
      timeout: 2000,
      cache: false
    });
    $("#<%=btnLoad.ClientID%>").on("click", function(evt) {
      evt.preventDefault();
      $.ajax({
        url: "Sample.html",
        dataType: "html",
        success: function(response) {
          $("#htmlcontent").html("").append(response);
        },
        error: function(jqXHR, textStatus, errorThrown) {
          if (textStatus == "error") {
            alert("An error has occurred: " + jqXHR.status + " " + jqXHR.statusText);
          }
        }
      });
      $.ajax({
        url: "Sample.xml",
        dataType: "xml",
        success: function(response) {
          $("#xmlcontent").html("").append("<h3>Book Shelf from XML</h3>");
          $("#xmlcontent").append("<table>");
          $("#xmlcontent table").append("<tr><th>Title</th><th>Author</th><th>Category</th></tr>");
          $(response).find("Book").each(function() {
            $("#xmlcontent table").append("<tr><td>" + $(this).find("Title").text() + "</td><td>" + $(this).find("Author").text() + "</td><td>" + $(this).find("Category").text() + "</td></tr>");
          });
        },
        error: function(jqXHR, textStatus, errorThrown) {
          if (textStatus == "error") {
            alert("An error has occurred: " + jqXHR.status + " " + jqXHR.statusText);
          }
        }
      });
    });
  });
</script>

How it works…

使用 Ajax 检索 HTML 和 XML 内容的步骤如下:

  1. When the page is launched, the $.ajaxSetup() function configures the global settings for all Ajax calls on the page:

    $.ajaxSetup({
      method: "GET",
      data: {},
      timeout: 2000,
      cache: false
    });
    

    它设置以下属性:

    • 请求的类型/方法设置为 HTTPGET
    • 空数据被发送到服务器
    • 设置了一个2000毫秒的超时,以便如果服务器在此时间范围内没有响应,可以终止调用
    • 缓存被设置为false,因此浏览器不会缓存请求的内容
  2. When you click on the button on the page, its corresponding click event handler is triggered:

    $("#<%=btnLoad.ClientID%>").on("click", function (evt) {…});
    

    在此事件处理程序中,首先,由于按钮click事件,阻止页面返回:

    evt.preventDefault();
    

    接下来,通过设置必要的选项来启动对Sample.html页面的 Ajax 调用:

    $.ajax({
      url: "Sample.html",
      dataType: "html",
      success: function (response) {
        $("#htmlcontent").html("").append(response);
      },
      error: function (jqXHR, textStatus, errorThrown) {
        if (textStatus == "error") {
          alert("An error has occurred: " + jqXHR.status + " " + jqXHR.statusText);
        }
      }
    });
    

    前面的代码片段在对 HTML 页面进行 Ajax 调用时设置了以下选项:

    • 请求 URL 设置为Sample.html
    • 服务器的预期响应的数据类型设置为html
    • 当向服务器发出的请求成功时,定义一个回调函数。 该功能清除 ID 为htmlcontentdiv区域的内容,并显示从相同 ID 的服务器接收的数据。
    • 当向服务器发出的请求失败时,定义一个回调函数。 这个回调函数有三个参数:jqXHR(XMLHttpRequest对象),textStatus(类型的错误,如abortparsererror,timeout,errornull),和【显示】(一个可选的异常对象)。 当textStatus参数为error时,我们显示jqXHR``XMLHttpRequest对象中的statusstatusText值。
  3. Next, initiate another Ajax call to the Sample.xml file with the required options:

    $.ajax({
      url: "Sample.xml",
      dataType: "xml",
      success: function(response) {
        $("#xmlcontent").html("").append("<h3>Book Shelf from XML</h3>");
        $("#xmlcontent").append("<table>");
        $("#xmlcontent table").append("<tr><th>Title</th><th>Author</th><th>Category</th></tr>");
        $(response).find("Book").each(function() {
          $("#xmlcontent table").append("<tr><td>" + $(this).find("Title").text() + "</td><td>" + $(this).find("Author").text() + "</td><td>" + $(this).find("Category").text() + "</td></tr>");
        });
      },
      error: function(jqXHR, textStatus, errorThrown) {
        if (textStatus == "error") {
          alert("An error has occurred: " + jqXHR.status + " " + jqXHR.statusText);
        }
      }
    });
    

    在上述请求中设置了以下选项:

    • 请求 URL 为Sample.xml

    • 服务器响应的预期数据类型为xml

    • 当向服务器发出的请求成功时,定义一个回调函数。 这个回调函数清除带有xmlcontentID 的div元素,并添加一个头部,如下面的代码片段所示:

    • 然后在这个div元素中添加一个空的表元素,并添加table标题:

      $("#xmlcontent").append("<table>");
      $("#xmlcontent table").append("<tr><th>Title</th><th>Author</th><th>Category</th></tr>");
      
    • 对于 XML 文件中的每个Book节点,它显示相应的子节点:TitleAuthorCategory,如下所示:

    • 当向服务器发出的请求不成功时,定义一个回调函数。 这个回调函数有三个参数:jqXHR(XMLHttpRequest对象),textStatus(类型的错误,如abortparsererror,timeout,errornull),和【显示】(一个可选的异常对象)。 当textStatus参数值为error时,我们显示XMLHttpRequest对象中的statusstatusText值。

还有更多的…

为了使用GET请求异步检索文本或 HTML 内容,jQuery 提供了一个.load()快捷方式。 使用这个函数,我们可以选择对Sample.html文件进行第一次 Ajax 调用,如下所示:

$("#htmlcontent").html("").load("Sample.html",
function (response, status, xhr) {
  if (status == "error") {
    alert("An error has occurred: " + xhr.status + " " + xhr.statusText);
  }
});

注意在这个函数中指定了一个回调函数。 这将在.load()方法完成时执行。 回调函数具有参数,如response(如果调用成功,其中包含结果内容)、status(其中包含调用的状态)和xhr(XMLHttpRequest对象)。

参见 also

消费页面方法配方

消耗页面方法

Page 方法提供了一种从客户端脚本调用服务器端代码的方便方法。 它们只是使用System.Web.Services.WebMethod标签装饰的服务器端方法。 在本菜谱中,我们将在页面方法中使用 Northwind 数据库来检索来自特定国家的客户列表。 该方法将使用 jQuery Ajax 从客户机脚本调用。

下表总结了本例中使用的结构:

|

构造

|

类型

|

描述

| | --- | --- | --- | | $("#identifier") | jQuery 选择器 | 这将根据元素的 ID 选择一个元素。 | | $("html_tag") | jQuery 选择器 | 这将选择具有指定 HTML 标记的所有元素。 | | $.ajax() | jQuery 函数 | 这将向服务器发送一个带有设置选项的 Ajax 请求。 | | .append() | jQuery 方法 | 这将在每个匹配元素的末尾插入内容。 | | click | jQuery 的事件 | 当您单击一个元素时,将触发此操作。 它对应于 JavaScript 的click事件。 | | event. preventDefault() | jQuery 方法 | 这将防止触发事件的默认动作。 | | :gt(i) | jQuery 选择器 | 这将选择索引大于i的匹配元素。 它使用一个从零开始的索引。 | | .hide() | jQuery 方法 | 这将隐藏匹配的元素。 | | :hidden | jQuery 选择器 | 这将选择隐藏元素。 | | .is() | jQuery 方法 | 如果匹配的元素满足给定条件,则返回一个布尔值。 | | .on() | jQuery 事件绑定 | 这将一个或多个事件的事件处理程序附加到匹配的元素。 | | .remove() | jQuery 方法 | 这会从 DOM 中删除匹配的元素。 | | .show() | jQuery 方法 | 这会显示匹配的元素。 | | .trim() | JavaScript 函数 | 这将删除字符串开头和结尾的空白。 | | .val() | jQuery 方法 | 返回第一个匹配元素的值,或者设置每个匹配元素的值。 | | window.location.href | JavaScript 的财产 | 这将返回当前页面的 URL。 |

准备

遵循以下步骤来构建一个公开页面方法的网页:

  1. Let's create a web page with a DropDownList control consisting of a list of countries, as shown in the following screenshot:

    Getting ready

    下拉菜单选择任意国家后,页面显示所选国家过滤的客户列表,如下图所示:

    Getting ready

  2. 要创建此应用,请启动ASP.NET Web 应用项目在 Visual Studio 中使用模板,并将其命名为Recipe2(或任何其他合适的名称)。

  3. 将 jQuery 库添加到项目的Scripts文件夹中。

  4. 添加一个 web 表单到项目中,并在表单中包含 jQuery 库。

  5. In the Solution Explorer tab, right-click on the project and go to Add | New Item. From the launched dialog box, select Data under the Installed templates section on the left-hand panel. Select ADO.NET Entity Data Model from the middle panel. Enter a suitable name for the model such as Northwind, and click on the Add button:

    Getting ready

  6. This will launch the Entity Data Model Wizard dialog box, as shown in the following screenshot. Select EF Designer from database and click on the Next button:

    Getting ready

    在下一个窗口中,添加到 Northwind 数据库的新连接。 将此连接保存在web.config中为NorthwindEntities,然后点击Next:

    Getting ready

    接下来,从表对象列表中检查Customers表,并点击Finish按钮:

    Getting ready

  7. In the code-behind file of the web form, that is, Default.aspx.vb (VB) or Default.aspx.cs (C#), add the following page method.

    对于 VB,代码如下:

    <System.Web.Services.WebMethod>
    Public Shared Function GetCustomers(ByVal sCountry As String) As Customer()
      Dim CustomerList As List(Of Customer) = New List(Of Customer)()
      Dim db As NorthwindEntities = New NorthwindEntities()
      Dim Query = From cust In db.Customers
      Where cust.Country = sCountry
      Select cust
    
      For Each custObj In Query
      Dim CustomerRecord As Customer = New Customer()
      CustomerRecord.CustomerID = custObj.CustomerID
      CustomerRecord.CompanyName = custObj.CompanyName
      CustomerRecord.ContactName = custObj.ContactName
      CustomerRecord.ContactTitle = custObj.ContactTitle
      CustomerRecord.City = custObj.City
      CustomerList.Add(CustomerRecord)
      Next
    
      Return CustomerList.ToArray
    End Function
    

    对于 c#,代码如下:

    [System.Web.Services.WebMethod]
    public static Customer[] GetCustomers(string sCountry)
    {
      List<Customer> CustomerList = new List<Customer>();
      NorthwindEntities db = new NorthwindEntities();
      var query = from cust in db.Customers
      where cust.Country == sCountry
      select cust;
      foreach (var custObj in query)
      {
        Customer CustomerRecord = new Customer();
        CustomerRecord.CustomerID = custObj.CustomerID;
        CustomerRecord.CompanyName = custObj.CompanyName;
        CustomerRecord.ContactName = custObj.ContactName;
        CustomerRecord.ContactTitle = custObj.ContactTitle;
        CustomerRecord.City = custObj.City;
        CustomerList.Add(CustomerRecord);
      }
      return CustomerList.ToArray();
    }
    
  8. The preceding GetCustomers()page method receives the country field as an input parameter. It filters customer records by country and returns an array of the Customer type.

    注意事项

    注意,页面方法需要有以下配置:

    • 该方法应装饰有System.Web.Services.WebMethod标签。
    • 它应该声明为共享(VB)或静态(c#)。
    • 它以sCountry作为输入参数。 这个参数应该由客户机脚本通过 Ajax 调用发送。
  9. 向 web 表单添加一个框架表元素,以显示检索到的客户列表。 因此,表单的标记如下:

    <asp:Label ID="lblSelectCountry" runat="server" Text="Please select the country to view customers:"></asp:Label><br /><br />
    <asp:DropDownList ID="ddlSelectCountry" runat="server">
      <asp:ListItem Text="--Select Country--" Value=""></asp:ListItem>
      <asp:ListItem Text="Argentina" Value="Argentina"></asp:ListItem>
      <asp:ListItem Text="Brazil" Value="Brazil"></asp:ListItem>
      <asp:ListItem Text="Canada" Value="Canada"></asp:ListItem>
      <asp:ListItem Text="Italy" Value="Italy"></asp:ListItem>
      <asp:ListItem Text="Mexico" Value="Mexico"></asp:ListItem>
      <asp:ListItem Text="UK" Value="UK"></asp:ListItem>
      <asp:ListItem Text="USA" Value="USA"></asp:ListItem>
    </asp:DropDownList>
    <asp:Button ID="btnRetrieve" runat="server" Text="Retrieve" />
    <br /><br />
    <table id="tblResponse">
      <thead>
        <tr>
          <th>Customer ID</th>
          <th>Company Name</th>
          <th>Contact Name</th>
          <th>Contact Title</th>
          <th>City</th>
        </tr>
      </thead>
    </table>
    
  10. 在页面上的head元素中添加以下样式:

怎么做……

<script>块中包含以下 jQuery 代码:

<script type="text/javascript">
  $(document).ready(function() {
    $("#tblResponse").hide();
    $("#<%=btnRetrieve.ClientID%>").on("click", function(evt) {
      evt.preventDefault();
      var sCountry = $("#<%=ddlSelectCountry.ClientID%>").val().trim();
      if (sCountry != "") {
        var loc = window.location.href;
        $.ajax({
          url: loc + "/GetCustomers",
          method: "POST",
          data: '{ "sCountry": "' + sCountry + '"}',
          dataType: "json",
          contentType: "application/json; charset=utf-8",
          timeout: 5000,
          cache: false,
          success: function(response) {
            $("#tblResponse tr:gt(0)").remove();
            if ($("#tblResponse").is(":hidden"))
              $("#tblResponse").show();
            $.each(response.d,
              function() {
                $("#tblResponse").append("<tr><td>" + this['CustomerID'] + "</td><td>" + this['CompanyName'] + "</td><td>" + this['ContactName'] + "</td><td>" + this['ContactTitle'] + "</td><td>" + this['City'] + "</td></tr>");
              });
          },
          error: function(jqXHR, textStatus, errorThrown) {
            if (textStatus == "error") {
              alert("An error has occurred: " + jqXHR.status + " " + jqXHR.statusText);
            }
          }
        });
      } else
        alert("Please select a country to display the customer list.");
    });
  });
</script>

How it works…

发布对页面方法的 Ajax 调用如下:

  1. 当页面启动时,用于显示客户列表的table元素最初是隐藏的:

    $("#tblResponse").hide();
    
  2. An event handler is defined for the click function of the button in the form:

    $("#<%=btnRetrieve.ClientID%>").on("click", function (evt) {…});
    

    在此事件处理程序中,使用以下代码阻止页面返回:

    evt.preventDefault();
    

    DropDownList控件中选取的值,即选取的国家:

    var sCountry = $("#<%=ddlSelectCountry.ClientID%>").val().trim();
    

    前面的字符串被调整以删除空白(如果有的话)。 如果所选国家非空,使用window.location.hrefJavaScript 属性找到当前页面的 URL:

    var loc = window.location.href;
    

    现在,对页面方法进行 Ajax 调用:

    $.ajax({
      url: loc + "/GetCustomers",
      method: "POST",
      data: '{ "sCountry": "' + sCountry + '"}',
      dataType: "json",
      contentType: "application/json; charset=utf-8",
      timeout: 5000,
      cache: false,
      success: function (response)
      $("#tblResponse tr:gt(0)").remove();
      if ($("#tblResponse").is(":hidden"))
        $("#tblResponse").show();
        $.each(response.d, function () {
          $("#tblResponse").append("<tr><td>" + this['CustomerID'] + "</td><td>" + this['CompanyName'] + "</td><td>" + this['ContactName'] + "</td><td>" + this['ContactTitle'] + "</td><td>" + this['City'] + "</td></tr>");
        });
      },
      error: function (jqXHR, textStatus, errorThrown) {
        if (textStatus == "error") {
          alert("An error has occurred: " + jqXHR.status + " " + jqXHR.statusText);
        }
      }
    });
    

    在上述通话中,设置了以下选项:

    • 请求 URL 被设置为页面方法,可以通过UrlOfCurrentPage/NameOfPageMethod访问。

    • 请求的类型/方法被设置为POST,因为我们正在向服务器发送表单数据。

    • The data, that is, the selected country is sent to the server as a JSON formatted string. Remember that the page method has an input parameter, sCountry. This is sent as a name/value pair as follows:

      data: '{ "sCountry": "' + sCountry + '"}',
      

      注意事项

      需要注意的是,前面 JSON 字符串中的sCountry名称是页面方法的输入参数。

    • 服务器响应的数据类型为json

    • 发送的请求内容类型设置为application/json,字符设置为UTF-8

    • 指定了一个5000毫秒的超时时间,在此时间之后,如果服务器没有响应,请求将被终止。

    • 缓存被设置为false,因此浏览器不会缓存内容。

    • 当请求成功时定义一个回调函数。 在这个函数中,显示表的内容被清空,删除除了表头以外的所有行:

      $("#tblResponse tr:gt(0)").remove();
      
    • 如果显示表被隐藏,则显示给用户:

      if ($("#tblResponse").is(":hidden"))
        $("#tblResponse").show();
      
    • 然后,我们循环遍历返回的响应中的每个元素,检索CustomerIDCompanyNameContactNameContactTitleCity字段,如下所示:

    注意事项

    注意,为了访问从服务器返回的数据,我们在前面的代码中使用了response.d

  3. 当请求不成功时,定义一个回调函数。 如果textStatus参数为error,则显示XmlHttpRequest对象的statusstatusText值。

  4. 用户也可能不从DropDownList控件中选择任何国家。 因此,当所选字段为空时,程序应该显示一条消息:

    alert("Please select a country to display the customer list.");
    

参见 also

对 HTTP 处理程序配方进行 AJAX 调用

使用 Web 服务

jQuery Ajax 允许您通过客户端代码使用 web 服务。 在这个食谱中,我们将表单数据发送到 web 服务方法。 本例中使用的结构总结如下表:

|

构造

|

类型

|

描述

| | --- | --- | --- | | $("#identifier") | jQuery 选择器 | 这将根据元素的 ID 选择一个元素。 | | $("html_tag") | jQuery 选择器 | 这将选择具有指定 HTML 标记的所有元素。 | | $.ajax() | jQuery 函数 | 这将向服务器发送一个带有设置选项的 Ajax 请求。 | | .append() | jQuery 方法 | 这将在每个匹配元素的末尾插入内容。 | | click | jQuery 的事件 | 当您单击一个元素时,它就会触发。 它对应于 JavaScript 的click事件。 | | event. preventDefault() | jQuery 方法 | 这将防止触发事件的默认动作。 | | .focus() | jQuery 事件绑定 | 这将触发元素的focus事件或将事件处理程序绑定到focus事件。 | | :gt(i) | jQuery 选择器 | 这将选择索引大于i的匹配元素。 它使用了从零开始的索引。 | | :hidden | jQuery 选择器 | 这将选择隐藏元素。 | | .hide() | jQuery 方法 | 这将隐藏匹配的元素。 | | .is() | jQuery 方法 | 如果匹配的元素满足给定条件,则返回一个布尔值。 | | .on() | jQuery 事件绑定 | 这将一个或多个事件的事件处理程序附加到匹配的元素。 | | .remove() | jQuery 方法 | 这会从 DOM 中删除匹配的元素。 | | .show() | jQuery 方法 | 这会显示匹配的元素。 | | .text() | jQuery 方法 | 这将返回每个匹配元素的组合文本内容,或者设置每个匹配元素的文本内容。 | | .trim() | JavaScript 函数 | 这将删除字符串开头和结尾的空白。 | | .val() | jQuery 方法 | 返回第一个匹配元素的值,或者设置每个匹配元素的值。 |

准备

遵循以下步骤构建一个将使用 web 服务的 web 页面:

  1. In this recipe, let's create a form where the user can search for employee records by the first name or last name, as shown in the following screenshot:

    Getting ready

    输入需要搜索的关键字,如果匹配,则显示搜索结果,如下图所示:

    Getting ready

    如果没有找到匹配的,页面只显示一条消息,如下图所示:

    Getting ready

  2. 要创建此应用,请启动ASP.NET Web 应用项目在 Visual Studio 中使用模板,并将其命名为Recipe3(或任何其他合适的名称)。

  3. 将 jQuery 库添加到项目中Scripts文件夹中。

  4. 添加一个 web 表单到项目中,并在表单中包含 jQuery 库。

  5. Include the following markup in the form:

    <h3>Key in the Employee name to search:</h3>
    <asp:TextBox ID="txtKeyword" runat="server"></asp:TextBox>
    <asp:Button ID="btnSearch" runat="server" Text="Search" />
    <br /><br />
    <table id="tblResponse">
      <thead>
        <tr>
          <th>Employee ID</th>
          <th>First Name</th>
          <th>Last Name</th>
          <th>City</th>
          <th>Country</th>
          <th>Home Phone</th>
        </tr>
      </thead>
    </table>
    <br />
    <asp:Label ID="lblMessage" runat="server"></asp:Label>
    

    注意,表单有一个Label控件lblMessage。 该字段将用于向用户显示信息/错误消息(如果有的话)。

  6. 使用下面的 CSS 样式来设置页面元素:

  7. Add an Employee class to the project by right-clicking on the project and navigating to Add | Class. Name the class Employee.vb (VB) or Employee.cs (C#). Add the following properties to the class.

    对于 VB,代码如下:

    Public Class Employee
      Public Property EmployeeID As String
      Public Property LastName As String
      Public Property FirstName As String
      Public Property City As String
      Public Property Country As String
      Public Property HomePhone As String
    End Class
    

    对于 c#,代码如下:

    public class Employee
    {
      public String EmployeeID { get; set; }
      public String LastName { get; set; }
      public String FirstName { get; set; }
      public String City{ get; set; }
      public String Country { get; set; }
      public String HomePhone { get; set; }
    }
    
  8. 现在,在Solution Explorer选项卡中右键单击项目,然后转到Add|New Folder。 将新文件夹命名为Services

  9. Right-click on the Services folder and go to Add | New Item. From the launched dialog box, select Web from the Installed templates on the left-hand side of the screen. From the middle panel, select Web Service (ASMX). Give the service a suitable name, such as NorthwindService.asmx, and click on the Add button:

    Getting ready

  10. In the code-behind file of NorthwindService.asmx, uncomment the following statements at the top of the file to enable the service to be accessed by Ajax:

对于 VB,声明如下:

```
<System.Web.Script.Services.ScriptService()>
```

对于 c#,语句如下:

```
[System.Web.Script.Services.ScriptService]
```
  1. Add the following namespace at the top of file. This will enable us to pick the Northwind database connection string from the web.config file.
对于 VB,代码如下:

```
Imports System.Web.Configuration
```

对于 c#,代码如下:

```
using System.Web.Configuration;
```
  1. Next, add a GetEmployeeResult()web method to the code-behind file.
对于 VB,代码如下:

```
<WebMethod()>
Public Function GetEmployeeResult(ByVal sSearch As String) As Employee()
  Dim employeeList As List(Of Employee) = New List(Of Employee)()
  Dim strConn As String = WebConfigurationManager.ConnectionStrings("NorthwindConnection").ConnectionString
  Dim con As SqlConnection = New SqlConnection(strConn)
  Dim strSql As String = "SELECT * FROM EMPLOYEES WHERE FirstName LIKE '%" + sSearch + "%' or LastName like '%" + sSearch + "%'"
  Dim cmd As SqlCommand = New SqlCommand(strSql, con)
  con.Open()
  Dim dr As SqlDataReader = cmd.ExecuteReader()
  While (dr.Read())
    Dim emp As Employee = New Employee()
    emp.EmployeeID = dr("EmployeeID").ToString()
    emp.FirstName = dr("FirstName").ToString()
    emp.LastName = dr("LastName").ToString()
    emp.City = dr("City").ToString()
    emp.Country = dr("Country").ToString()
    emp.HomePhone = dr("HomePhone").ToString()
    employeeList.Add(emp)
  End While
  con.Close()
  Return employeeList.ToArray()
End Function
```

对于 c#,代码如下:

```
[WebMethod]
public Employee[] GetEmployeeResult(String sSearch)
{
  List<Employee> employeeList = new List<Employee>();
  String strConn = WebConfigurationManager.ConnectionStrings["NorthwindConnection"].ConnectionString;
  SqlConnection con = new SqlConnection(strConn);
  String strSql = "SELECT * FROM EMPLOYEES WHERE FirstName LIKE '%" + sSearch + "%' or LastName like '%" + sSearch + "%'";
  SqlCommand cmd = new SqlCommand(strSql, con);
  con.Open();
  SqlDataReader dr = cmd.ExecuteReader();
  while (dr.Read())
  {
    Employee emp = new Employee();
    emp.EmployeeID = dr["EmployeeID"].ToString();
    emp.FirstName = dr["FirstName"].ToString();
    emp.LastName = dr["LastName"].ToString();
    emp.City = dr["City"].ToString();
    emp.Country = dr["Country"].ToString();
    emp.HomePhone = dr["HomePhone"].ToString();
    employeeList.Add(emp);
  }
  con.Close();
  return employeeList.ToArray();
}
```

前面代码中定义的 web 方法从调用程序接收一个搜索关键字。 然后,它使用 ADO 连接到 Northwind 数据库.NET 并查询`Employees`表,以返回`FirstName`或`LastName`列包含搜索关键字的记录。 记录列表作为`Employee`类型的数组返回。

### 注意事项

请注意,调用程序需要将`sSearch`输入参数传递给 web 方法。
  1. web.config文件的配置部分将连接字符串添加到 Northwind 数据库:
```
<connectionStrings>
  <add name="NorthwindConnection" providerName="System.Data.SqlClient" connectionString="Data Source=localhost;Initial Catalog=Northwind;Integrated Security=True;"/>
</connectionStrings>
```

注意事项

请注意在本书中,我们对所有数据库驱动的示例都使用 Windows 身份验证。 因此,在 MS SQL Server 中,给 Windows 帐户访问 Northwind 数据库的权限是很重要的。

怎么做……

在页面的<script>块中包含以下 jQuery 代码:

$(document).ready(function () {
  $("#tblResponse").hide();
  $("#<%=lblMessage.ClientID%>").hide();
  $("#<%=txtKeyword.ClientID%>").focus();
  $("#<%=btnSearch.ClientID%>").on("click", function (evt) {
    evt.preventDefault();
    $("#<%=lblMessage.ClientID%>").hide();
    var sKeyword = $("#<%=txtKeyword.ClientID%>").val().trim();
    if (sKeyword != "") {
      $.ajax({
        url: "/Services/NorthwindService.asmx/GetEmployeeResult",
        type: "POST",
        data: '{ "sSearch": "' + sKeyword + '"}',
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        timeout: 5000,
        cache: false,
        success: function (response) {
          $("#tblResponse tr:gt(0)").remove();
          if ($("#tblResponse").is(":hidden"))
            $("#tblResponse").show();
          if (response.d.length > 0) {
            $.each(response.d, function () {
              ("#tblResponse").append("<tr><td>" + this['EmployeeID'] + "</td><td>" + this['FirstName'] + "</td><td>" + this['LastName'] + "</td><td>" + this['City'] + "</td><td>" + this['Country'] + "</td><td>" + this['HomePhone'] + "</td></tr>");
            });
          } else $("#<%=lblMessage.ClientID%>").text("No results").show();
        },
        error: function (jqXHR, textStatus, errorThrown) {
          if (textStatus == "error") {
            alert("An error has occurred: " + jqXHR.status + " " + jqXHR.statusText);}
          }
       });
    }
    else
      alert("Please enter your search keyword");
    });
  });
</script>

How it works…

对 web 服务的 Ajax 调用如下:

  1. 当页面启动时,将向用户显示一个文本字段,以便键入搜索关键字。 在页面上完成以下初始化:

    • 结果表被隐藏,如下:

      $("#tblResponse").hide();
      
    • 用于显示信息/错误信息的标签被隐藏:

      $("#<%=lblMessage.ClientID%>").hide();
      
    • 光标聚焦在文本字段上,以便用户键入所需的搜索关键字:

      $("#<%=txtKeyword.ClientID%>").focus();
      
  2. An event handler is attached in order to respond to the click event of the button on the page:

    $("#<%=btnSearch.ClientID%>").on("click", function (evt) {…});
    

    在此事件处理程序中,使用以下代码阻止页面返回:

    evt.preventDefault();
    

    前面的查询可能会显示信息/错误消息,因此lblMessage控件再次被隐藏:

    $("#<%=lblMessage.ClientID%>").hide();
    

    接下来,检索在文本字段中输入的搜索关键字。 白色空间,如果有,将被裁剪:

    var sKeyword = $("#<%=txtKeyword.ClientID%>").val().trim();
    

    如果关键字不为空,则使用 HTTP POST 对 web 服务进行 Ajax 调用:

    if (sKeyword != "") {
      $.ajax({
        url: "/Services/NorthwindService.asmx/GetEmployeeResult",
        type: "POST",
        data: '{ "sSearch": "' + sKeyword + '"}',
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        timeout: 5000,
        cache: false,
        success: function(response) {
          $("#tblResponse tr:gt(0)").remove();
          if ($("#tblResponse").is(":hidden"))
            $("#tblResponse").show();
          if (response.d.length > 0) {
            $.each(response.d, function() {
              $("#tblResponse").append("<tr><td>" +
              this['EmployeeID'] + "</td><td>" + this['FirstName'] +
              "</td><td>" + this['LastName'] + "</td><td>" + this['City'] + "</td><td>" + this['Country'] + "</td><td>" + this['HomePhone'] + "</td></tr>");
            });
          } else $("#<%=lblMessage.ClientID%>").text("No 
            results ").show();
          },
          error: function(jqXHR, textStatus, errorThrown) {
            if (textStatus == "error") {
              alert("An error has occurred: " + jqXHR.status + " " + jqXHR.statusText);
            }
          }
        });
    }
    

    在前面的 Ajax 调用中,设置了以下选项:

    • 请求 URL 设置为WebServicePath/WebMethodName

    • HTTP 请求类型/方法设置为POST

    • 数据由一个 JSON 格式的字符串组成。 搜索关键字使用名称/值对发送。 名称设置为sSearch,值设置为从文本字段中检索到的字符串。 JSON 格式字符串如下:

      '{ "sSearch": "' + sKeyword + '"}'
      
    • 响应的预期数据类型设置为json

    • 内容类型设置为application/json,字符设置为utf-8

    • 指定了一个5000毫秒的超时时间,以便如果服务器在此时间范围内未能响应,请求将终止。

    • 缓存被设置为false,因此响应不会缓存在浏览器中。

    • 为成功完成 Ajax 调用指定了一个回调函数。 该函数首先清除所有先前显示的项目的显示表:

      $("#tblResponse tr:gt(0)").remove();
      
    • 如果表是隐藏的,它是可见的:

    • 接下来,它检查响应是否为非空。 这可以通过检查response.d的长度来实现。 如果响应非空,则显示响应数组中的每个项:

      if (response.d.length > 0) {
        $.each(response.d, function () {
          $("#tblResponse").append("<tr><td>" + this['EmployeeID'] + "</td><td>" + this['FirstName'] + "</td><td>" + this['LastName'] + "</td><td>" + this['City'] + "</td><td>" + this['Country'] + "</td><td>" + this['HomePhone'] + "</td></tr>");
        });
      }
      
    • 但是,如果响应为空,则使用lblMessage控件显示一个错误,如下所示:

  3. 为不成功的 Ajax 调用指定一个回调函数。 在发生错误时,它显示XmlHttpObjectstatusstatusText参数。

  4. 但是,如果用户单击按钮时搜索关键字为空,则向用户显示以下错误信息:

    alert("Please enter your search keyword");
    

参见 also

消费 WCF 服务配方

使用 WCF 服务

消费 WCF 服务类似于消费 web 服务,如前面的配方中所述。 在本例中,我们将重做前面的配方,但这次使用的是 WCF 服务。 本例中使用的构造总结如下表:

|

构造

|

类型

|

描述

| | --- | --- | --- | | $("#identifier") | jQuery 选择器 | 这将根据元素的 ID 选择一个元素。 | | $("html_tag") | jQuery 选择器 | 这将选择具有指定 HTML 标记的所有元素。 | | $.ajax() | jQuery 函数 | 这将向服务器发送一个带有设置选项的 Ajax 请求。 | | .append() | jQuery 方法 | 这将在每个匹配元素的末尾插入内容。 | | click | jQuery 的事件 | 当您单击一个元素时,它就会触发。 它对应于 JavaScript 的click事件。 | | event. preventDefault() | jQuery 方法 | 这将防止触发事件的默认动作。 | | .focus() | jQuery 事件绑定 | 这将触发元素的focus事件或将事件处理程序绑定到focus事件。 | | :gt(i) | jQuery 选择器 | 这将选择索引大于i的匹配元素。 它使用了从零开始的索引。 | | :hidden | jQuery 选择器 | 这将选择隐藏元素。 | | .hide() | jQuery 方法 | 这将隐藏匹配的元素。 | | .is() | jQuery 方法 | 如果匹配的元素满足给定条件,则返回一个布尔值。 | | .on() | jQuery 事件绑定 | 这将一个或多个事件的事件处理程序附加到匹配的元素。 | | .remove() | jQuery 方法 | 这会从 DOM 中删除匹配的元素。 | | .show() | jQuery 方法 | 这会显示匹配的元素。 | | .text() | jQuery 方法 | 这会返回每个匹配元素的组合文本内容,或者设置每个匹配元素的文本内容。 | | .trim() | JavaScript 函数 | 这将删除字符串开头和结尾的空白。 | | .val() | jQuery 方法 | 返回第一个匹配元素的值,或者设置每个匹配元素的值。 |

准备

按照的步骤来构建一个使用 WCF 服务的页面:

  1. Similar to the previous recipe, the goal here is to search for employee records by the first or last name. When a match is found, the records are displayed, as shown in the following screenshot:

    Getting ready

    如果没有找到匹配项,页面会向用户显示相应的消息:

    Getting ready

  2. 要创建此应用,请启动ASP.NET Web 应用项目在 Visual Studio 中使用空的模板,并将其命名为Recipe4(或其他合适的名称)。

  3. 将 jQuery 库添加到项目中Scripts文件夹中。

  4. 添加一个 web 表单到项目中,并在表单中包含 jQuery 库。

  5. Include the following markup in the form:

    <h3>Key in the Employee name to search:</h3>
    <asp:TextBox ID="txtKeyword" runat="server"></asp:TextBox>
    <asp:Button ID="btnSearch" runat="server" Text="Search" />
    <br /><br />
    <table id="tblResponse">
      <thead>
        <tr>
          <th>Employee ID</th>
          <th>First Name</th>
          <th>Last Name</th>
          <th>City</th>
          <th>Country</th>
          <th>Home Phone</th>
        </tr>
      </thead>
    </table>
    <br />
    <asp:Label ID="lblMessage" runat="server"></asp:Label>
    

    注意,表单有一个Label控件lblMessage。 该字段将用于向用户显示信息/错误消息(如果有的话)。

  6. 使用下面的 CSS 样式来设置页面元素:

  7. Add an Employee class to the project by right-clicking on the project and navigating to Add | Class. Name the class Employee.vb (VB) or Employee.cs (C#). Add the following properties to the class.

    对于 VB,代码如下:

    Public Class Employee
      Public Property EmployeeID As String
      Public Property LastName As String
      Public Property FirstName As String
      Public Property City As String
      Public Property Country As String
      Public Property HomePhone As String
    End Class
    

    对于 c#,代码如下:

    public class Employee
    {
      public String EmployeeID { get; set; }
      public String LastName { get; set; }
      public String FirstName { get; set; }
      public String City{ get; set; }
      public String Country { get; set; }
      public String HomePhone { get; set; }
    }
    
  8. 接下来,我们将向项目添加一个 WCF 服务。 要做到这一点,右键单击Solution Explorer选项卡中的项目,然后转到Add|New Folder。 将新文件夹命名为Services

  9. Right-click on the Services folder and go to Add | New Item. From the launched dialog box, select Web from the Installed templates on the left-hand side of the screen. From the middle panel, select WCF Service (Ajax-enabled). Give the service a suitable name such as NorthwindService.svc, and click on the Add button:

    Getting ready

  10. In the code-behind file of NorthwindService.svc, add the following namespace in order to enable us to retrieve the Northwind database connection string from web.config.

对于 VB,命名空间如下:

```
Imports System.Web.Configuration
```

对于 c#,命名空间如下所示:

```
using System.Web.Configuration;
```
  1. Next, add the GetEmployeeResult()operation contract to the preceding code-behind file.
对于 VB,代码如下:

```
<OperationContract()>
Public Function GetEmployeeResult(ByVal sSearch As String) As Employee()
  Dim employeeList As List(Of Employee) = New List(Of Employee)()
  Dim strConn As String = WebConfigurationManager.ConnectionStrings("NorthwindConnection").ConnectionString
  Dim con As SqlConnection = New SqlConnection(strConn)
  Dim strSql As String = "SELECT * FROM EMPLOYEES WHERE FirstName LIKE '%" + sSearch + "%' or LastName like '%" + sSearch + "%'"
  Dim cmd As SqlCommand = New SqlCommand(strSql, con)
  con.Open()
  Dim dr As SqlDataReader = cmd.ExecuteReader()
  While (dr.Read())
    Dim emp As Employee = New Employee()
    emp.EmployeeID = dr("EmployeeID").ToString()
    emp.FirstName = dr("FirstName").ToString()
    emp.LastName = dr("LastName").ToString()
    emp.City = dr("City").ToString()
    emp.Country = dr("Country").ToString()
    emp.HomePhone = dr("HomePhone").ToString()
    employeeList.Add(emp)
  End While
  con.Close()
  Return employeeList.ToArray()
End Function
```

对于 c#,代码如下:

```
[OperationContract]
public Employee[] GetEmployeeResult(String sSearch)
{
  List<Employee> employeeList = new List<Employee>();
  String strConn = WebConfigurationManager.ConnectionStrings["NorthwindConnection"].ConnectionString;
  SqlConnection con = new SqlConnection(strConn);
  String strSql = "SELECT * FROM EMPLOYEES WHERE FirstName LIKE '%" + sSearch + "%' or LastName like '%" + sSearch + "%'";
  SqlCommand cmd = new SqlCommand(strSql, con);
  con.Open();
  SqlDataReader dr = cmd.ExecuteReader();
  while (dr.Read())
  {
    Employee emp = new Employee();
    emp.EmployeeID = dr["EmployeeID"].ToString();
    emp.FirstName = dr["FirstName"].ToString();
    emp.LastName = dr["LastName"].ToString();
    emp.City = dr["City"].ToString();
    emp.Country = dr["Country"].ToString();
    emp.HomePhone = dr["HomePhone"].ToString();
    employeeList.Add(emp);
  }
  con.Close();
  return employeeList.ToArray();
}
```

操作契约从调用程序接收一个搜索关键字。 然后,它使用 ADO 连接到 Northwind 数据库.NET 并查询`Employees`表,以返回`FirstName`或`LastName`列包含搜索关键字的记录。 记录的列表作为`Employee`类型的数组返回。

### 注意事项

注意,调用程序需要将`sSearch`输入参数传递给 WCF 操作契约。
  1. web.config文件的配置部分向 Northwind 数据库添加一个连接字符串:
```
<connectionStrings>
  <add name="NorthwindConnection" providerName="System.Data.SqlClient" connectionString="Data Source=localhost;Initial Catalog=Northwind;Integrated Security=True;"/>
</connectionStrings>
```

注意事项

请注意,本书中所有数据库驱动的示例都使用 Windows 身份验证。 因此,在 MS SQL Server 中,给 Windows 帐户访问 Northwind 数据库的权限是很重要的。

怎么做……

在页面的<script>块中包含以下 jQuery 代码:

<script type="text/javascript">
  $(document).ready(function() {
    $("#tblResponse").hide();
    $("#<%=lblMessage.ClientID%>").hide();
    $("#<%=txtKeyword.ClientID%>").focus();
    $("#<%=btnSearch.ClientID%>").on("click", function(evt) {
      evt.preventDefault();
      $("#<%=lblMessage.ClientID%>").hide();
      var sKeyword = $("#<%=txtKeyword.ClientID%>").val().trim();
      if (sKeyword != "") {
        $.ajax({
          url: "/Services/NorthwindService.svc/GetEmployeeResult",
          type: "POST",
          data: '{ "sSearch": "' + sKeyword + '"}',
          dataType: "json",
          contentType: "application/json; charset=utf-8",
          timeout: 5000,
          cache: false,
          success: function(response) {
            $("#tblResponse tr:gt(0)").remove();
            if ($("#tblResponse").is(":hidden"))
              $("#tblResponse").show();
            if (response.d.length > 0) {
              $.each(response.d, function() {
                $("#tblResponse").append("<tr><td>" + this['EmployeeID'] + "</td><td>" + this['FirstName'] + "</td><td>" + this['LastName'] + "</td><td>" + this['City'] + "</td><td>" + this['Country'] + "</td><td>" + this['HomePhone'] + "</td></tr>");
              });
            } else
              $("#<%=lblMessage.ClientID%>").text("No results").show();
          },
          error: function(jqXHR, textStatus, errorThrown) {
            if (textStatus == "error") {
              alert("An error has occurred: " + jqXHR.status + " " + jqXHR.statusText);
            }
          }
        });
      } else
        alert("Please enter your search keyword");
    });
  });
</script>

How it works…

对 WCF 服务的 Ajax 调用如下:

  1. 当页面启动时,将向用户显示一个文本字段,用于键入搜索关键字。 在页面上完成以下初始化:

    • 结果表最初使用以下方法隐藏:

    • 用于显示信息/错误消息的 Label 字段也被隐藏:

      $("#<%=lblMessage.ClientID%>").hide();
      
    • 光标聚焦于文本字段,以便用户键入所需的关键字:

      $("#<%=txtKeyword.ClientID%>").focus();
      
  2. An event handler is defined to respond to the click event of the button on the page:

    $("#<%=btnSearch.ClientID%>").on("click", function (evt) {…});
    

    在此事件处理程序中,使用以下方法阻止页面发回:

    evt.preventDefault();
    

    前面的查询可能会显示信息/错误消息,因此lblMessage控件再次被隐藏:

    $("#<%=lblMessage.ClientID%>").hide();
    
  3. Next, the keyword entered in the text field is retrieved. Whitespaces, if any, are trimmed:

    var sKeyword = $("#<%=txtKeyword.ClientID%>").val().trim();
    

    如果关键字不为空,则对 Web 服务进行 Ajax 调用:

    if (sKeyword != "") {
      $.ajax({
        url: "/Services/NorthwindService.svc/GetEmployeeResult",
        type: "POST",
        data: '{ "sSearch": "' + sKeyword + '"}',
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        timeout: 5000,
        cache: false,
        success: function(response) {
          $("#tblResponse tr:gt(0)").remove();
          if ($("#tblResponse").is(":hidden"))
            $("#tblResponse").show();
          if (response.d.length > 0) {
            $.each(response.d,
              function() {
                $("#tblResponse").append("<tr><td>" + this['EmployeeID'] + "</td><td>" + this['FirstName'] + "</td><td>" + this['LastName'] + "</td><td>" + this['City'] + "</td><td>" + this['Country'] + "</td><td>" + this['HomePhone'] + "</td></tr>");
              });
          } else $("#<%=lblMessage.ClientID%>").text("No results").show();
        },
        error: function(jqXHR, textStatus, errorThrown) {
          if (textStatus == "error") {
            alert("An error has occurred: " + jqXHR.status + " " + jqXHR.statusText);
          }
        }
      });
    }
    

    在前面的 Ajax 调用中,设置了以下选项:

    • 请求 URL 被设置为 WCFPath/OperationContract。

    • HTTP 请求类型/方法设置为POST

    • 数据由一个 JSON 格式的字符串组成。 搜索关键字以名称/值对的形式发送。 名称设置为sSearch,值设置为从文本字段中检索到的字符串,如下所示:

    • 响应的预期数据类型设置为json

    • 内容类型设置为application/json,字符设置为utf-8

    • 指定了一个5000毫秒的超时时间,以便如果服务器在此时间范围内未能响应,请求将终止。

    • 缓存被设置为false,因此响应不会缓存在浏览器中。

    • 为成功完成 Ajax 调用指定了一个回调函数。 此功能首先清除显示表:

      $("#tblResponse tr:gt(0)").remove();
      
    • 如果表是隐藏的,那么它就是可见的。

      if ($("#tblResponse").is(":hidden"))
        $("#tblResponse").show();
      
  4. Next, it checks whether the response is nonempty. This can be done by checking the length of response.d. If the response is nonempty, each item in the response array is displayed:

    if (response.d.length > 0) {
      $.each(response.d, function () {
        $("#tblResponse").append("<tr><td>" + this['EmployeeID'] + "</td><td>" + this['FirstName'] + "</td><td>" + this['LastName'] + "</td><td>" + this['City'] + "</td><td>" + this['Country'] + "</td><td>" + this['HomePhone'] + "</td></tr>");
      });
    }
    

    但是,如果响应为空,则使用lblMessage控件显示错误:

    $("#<%=lblMessage.ClientID%>").text("No results").show();
    
  5. 为不成功的 Ajax 调用指定了一个回调函数。 在发生错误时,它显示XmlHttpObjectstatusstatusText参数。

  6. 但是,如果用户单击Button控件时搜索关键字为空,则向用户显示以下错误消息:

    alert("Please enter your search keyword");
    

参见 also

消费 Web 服务配方

从 Web API 中检索数据

Web API(Web 应用编程接口)是使用. net 框架创建的 HTTP API。 它使用 HTTP 协议返回数据。 由于 HTTP 可以在广泛的平台上使用,所以这些 api 可以在 Web 和移动平台上使用,也可以跨各种设备使用。

在这个例子中,我们将使用 jQuery Ajax 向 Web API 发布一个请求。 下表总结了本例中使用的结构:

|

构造

|

类型

|

描述

| | --- | --- | --- | | $("#identifier") | jQuery 选择器 | 这将根据元素的 ID 选择一个元素。 | | $("html_tag") | jQuery 选择器 | 这将选择具有指定 HTML 标记的所有元素。 | | $.getJSON() | jQuery 函数 | 这将使用 HTTPGET请求从服务器加载 JSON 数据。 | | .append() | jQuery 方法 | 这将在每个匹配元素的末尾插入内容。 | | click | jQuery 的事件 | 当您单击一个元素时,它就会触发。 它对应于 JavaScript 的click事件。 | | event. preventDefault() | jQuery 方法 | 这将防止触发事件的默认动作。 | | .focus() | jQuery 事件绑定 | 这将触发元素的focus事件或将事件处理程序绑定到focus事件。 | | :gt(i) | jQuery 选择器 | 这将选择索引大于i的匹配的元素。 它使用一个从零开始的索引。 | | .hide() | jQuery 方法 | 这将隐藏匹配的元素。 | | :hidden | jQuery 选择器 | 这将选择隐藏元素。 | | .is() | jQuery 方法 | 如果匹配的元素满足给定条件,则返回一个布尔值。 | | .on() | jQuery 事件绑定 | 这将一个或多个事件的事件处理程序附加到匹配的元素。 | | .remove() | jQuery 方法 | 这会从 DOM 中删除匹配的元素。 | | .show() | jQuery 方法 | 这会显示匹配的元素。 | | .text() | jQuery 方法 | 这将返回每个匹配元素的组合文本内容,或者设置每个匹配元素的文本内容。 | | .trim() | JavaScript 函数 | 这将删除字符串开头和结尾的空白。 | | .val() | jQuery 方法 | 返回第一个匹配元素的值,或者设置每个匹配元素的值。 |

准备

按照以下步骤构建一个从 Web API 加载数据的页面:

  1. Let's create a web page that allows you to search for customer records from the Northwind database using either Customer ID or Customer Name. When a match is found, the results are returned, as shown in the following screenshot:

    Getting ready

    如果没有匹配,则显示,如下图所示:

    Getting ready

  2. To create this application, launch an ASP.NET Web Application project in Visual Studio using the Empty template and name it Recipe5 (or any other suitable name).

    注意事项

    注意,我们在这个食谱中使用的是空的模板。 如果从可用的模板中选择了Web API,则使用 ASP 创建 API。 净 MVC。

  3. 将 jQuery 库添加到项目的Scripts文件夹中。

  4. 添加一个 web 表单到项目中,并在表单中包含 jQuery 库。 在head元素中,添加以下样式:

  5. Add a Model folder by right-clicking on the project in the Solution Explorer tab and navigating to Add | New Folder. Next, right-click on the Model folder and go to Add | Class. Name the class Customer.vb (VB) or Customer.cs (C#). Add the following properties to this file.

    对于 VB,代码如下:

    Public Class Customer
      Public Property CustomerID As String
      Public Property CompanyName As String
      Public Property ContactName As String
      Public Property Phone As String
      Public Property Country As String
    End Class
    

    对于 c#,添加以下代码:

    public class Customer
    {
      public String CustomerID { get; set;}
      public String CompanyName { get; set; }
      public String ContactName { get; set; }
      public String Country { get; set; }
      public String Phone { get; set; }
    }
    
  6. Add a Controllers folder by right-clicking on the project and navigating to Add | New Folder. Next, right-click on the Controllers folder and go to Add | Controller. Select Web API 2 Controller – Empty from the list of available templates, as shown in the following screenshot, and click on the Add button:

    Getting ready

    在下一个对话框中,为控制器输入一个合适的名称。 我们将控制器命名为CustomerController:

    Getting ready

  7. Open the code-behind file of CustomerController, that is, CustomerController.vb (VB) or CustomerController.cs (C#) and add the following methods.

    对于 VB,代码如下:

    ' GET api/<controller>/keyword
    Public Function GetCustomers(ByVal searchKeyword As String) As IEnumerable(Of Customer)
      Dim customers As New List(Of Customer)
      Dim con As New SqlConnection(WebConfigurationManager.ConnectionStrings("NorthwindConnection").ConnectionString)
      Dim strQuery As String = "SELECT * FROM CUSTOMERS WHERE CUSTOMERID LIKE '%" + searchKeyword + "%' OR COMPANYNAME LIKE '%" + searchKeyword + "%'"
      Dim cmd As New SqlCommand(strQuery, con)
      con.Open()
      Dim reader As SqlDataReader = cmd.ExecuteReader()
      While (reader.Read())
        Dim cust As New Customer()
        cust.CustomerID = reader("CustomerID").ToString()
        cust.CompanyName = reader("CompanyName").ToString()
        cust.ContactName = reader("ContactName").ToString()
        cust.Country = reader("Country").ToString()
        cust.Phone = reader("Phone").ToString()
        customers.Add(cust)
      End While
      con.Close()
      Return customers
    End Function
    
    ' GET api/<controller>
    Public Function GetAllCustomers() As IEnumerable(Of Customer)
      Dim customers As New List(Of Customer)
      Dim con As New SqlConnection(WebConfigurationManager.ConnectionStrings("NorthwindConnection").ConnectionString)
      Dim strQuery As String = "SELECT * FROM CUSTOMERS"
      Dim cmd As New SqlCommand(strQuery, con)
      con.Open()
      Dim reader As SqlDataReader = cmd.ExecuteReader()
      While (reader.Read())
        Dim cust As New Customer()
        cust.CustomerID = reader("CustomerID").ToString()
        cust.CompanyName = reader("CompanyName").ToString()
        cust.ContactName = reader("ContactName").ToString()
        cust.Country = reader("Country").ToString()
        cust.Phone = reader("Phone").ToString()
        customers.Add(cust)
      End While
      con.Close()
      Return customers
    End Function
    

    对于 c#,代码如下所示:

    public IEnumerable<Customer> GetCustomers(String searchKeyword)
    {
      List<Customer> customers = new List<Customer>();
      SqlConnection con = new SqlConnection(WebConfigurationManager.ConnectionStrings["NorthwindConnection"].ConnectionString);
      String strQuery = "SELECT * FROM CUSTOMERS WHERE CUSTOMERID LIKE '%" + searchKeyword + "%' OR COMPANYNAME LIKE '%" + searchKeyword + "%'" ;
      SqlCommand cmd = new SqlCommand(strQuery, con);
      con.Open();
      SqlDataReader reader = cmd.ExecuteReader();
      while (reader.Read())
      {
        Customer cust = new Customer();
        cust.CustomerID = reader["CustomerID"].ToString();
        cust.CompanyName = reader["CompanyName"].ToString();
        cust.ContactName = reader["ContactName"].ToString();
        cust.Country = reader["Country"].ToString();
        cust.Phone = reader["Phone"].ToString();
        customers.Add(cust);
      }
      con.Close();
      return customers;
    }
    public IEnumerable<Customer> GetAllCustomers()
    { 
      List<Customer> customers = new List<Customer>();
      SqlConnection con = new SqlConnection(WebConfigurationManager.ConnectionStrings["NorthwindConnection"].ConnectionString);
      String strQuery = "SELECT * FROM CUSTOMERS";
      SqlCommand cmd = new SqlCommand(strQuery, con);
      con.Open();
      SqlDataReader reader = cmd.ExecuteReader();
      while (reader.Read())
      {
        Customer cust = new Customer();
        cust.CustomerID = reader["CustomerID"].ToString();
        cust.CompanyName = reader["CompanyName"].ToString();
        cust.ContactName = reader["ContactName"].ToString();
        cust.Country = reader["Country"].ToString();
        cust.Phone = reader["Phone"].ToString();
        customers.Add(cust);
      }
      con.Close();
      return customers;
    }
    

    我们在 Web API 中定义了两个GET方法。 GetCustomers()方法接受searchKeyword字符串参数并返回 Northwind 数据库的Customer表中所有客户的列表,其中CustomerIDCustomerName列包含此关键字。 第二个GetAllCustomers()方法不接受参数,并返回Customer表中的全部记录集。

    另外,在文件的顶部添加以下名称空间。

    对于 VB,命名空间如下:

    Imports System.Web.Http
    Imports System.Data.SqlClient
    Imports System.Web.Configuration
    

    对于 c#,命名空间如下所示:

    using System.Web.Http;
    using System.Data.SqlClient;
    using System.Web.Configuration;
    
  8. To connect to the Northwind database, add the following connection string to the configuration section of web.config:

    <connectionStrings>
      <add name="NorthwindConnection" providerName="System.Data.SqlClient" connectionString="Data Source=localhost;Initial Catalog=Northwind;Integrated Security=True;"/>
    </connectionStrings>
    

    提示

    记住要允许 Windows 帐户访问 Northwind 数据库。

  9. Add the routing information to the Web API in the Application_Start procedure in Global.asax.

    对于 VB,代码如下:

    Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
      RouteTable.Routes.MapHttpRoute("CustomerApi", "api/{controller}/{searchKeyword}",
      defaults:=New With {.searchKeyword = System.Web.Http.RouteParameter.Optional})
    End Sub
    

    对于 c#,代码如下:

    protected void Application_Start(object sender, EventArgs e)
    {
      RouteTable.Routes.MapHttpRoute(
        name: "CustomerApi",
        routeTemplate: "api/{controller}/{searchKeyword}",
        defaults: new { searchKeyword = RouteParameter.Optional }
      );
    }
    

这个暴露了 Web API 在api/controller/keyword的方法。

注意事项

如果RouteTable.Routes.MapHttpRoute不能识别方法,引用添加到System.Web.HttpSystem.Web.Http.WebHost议会通过右键单击解决方案资源管理器中项目选项卡并导航到添加|引用【显示】。

怎么做……

添加以下 jQuery 代码到页面的<script>块:

<script type="text/javascript">
  $(document).ready(function() {
    $("#tblResponse").hide();
    $("#<%=lblMessage.ClientID%>").hide();
    $("#<%=txtKeyword.ClientID%>").focus();
    $("#<%=btnSearch.ClientID%>").on("click", function(evt) {
      evt.preventDefault();
      $("#<%=lblMessage.ClientID%>").hide();
      var sKeyword = $("#<%=txtKeyword.ClientID%>").val().trim();
      var uri = ((sKeyword == "") ? "api/customer" : "api/customer/" + sKeyword);
      $.getJSON(uri).done(function(data) {
        $("#tblResponse tr:gt(0)").remove();
        if ($("#tblResponse").is(":hidden"))
          $("#tblResponse").show();
        if (data.length > 0) {
          $.each(data, function(key, val) {
            $("#tblResponse").append("<tr><td>" + val.CustomerID + "</td><td>" + val.CompanyName + "</td><td>" + val.ContactName + "</td><td>" + val.Phone + "</td><td>" + val.Country + "</td></tr>");
          });
        } else
          $("#<%=lblMessage.ClientID%>").text("No results").show();
      }).fail(function(jqXHR, textStatus, errorThrown) {
        alert("An error has occurred: " + textStatus + " " + errorThrown);
      });
    });
  });
</script>

How it works…

对 Web API 的 Ajax 调用是通过以下步骤进行的:

  1. 当页面加载时,结果表将对用户隐藏:

    $("#tblResponse").hide();
    
  2. 用于向用户显示信息/错误消息的label控件最初也是隐藏的:

    $("#<%=lblMessage.ClientID%>").hide();
    
  3. 接下来,光标聚焦于搜索关键字文本字段:

    $("#<%=txtKeyword.ClientID%>").focus();
    
  4. The page will call the Web API when you click on the Search button. Hence, we write an event handler for the click event of this button:

    $("#<%=btnSearch.ClientID%>").on("click", function (evt) {…});
    

    在这个事件处理程序中,页面将被阻止发回,如下所示:

    evt.preventDefault();
    

    接下来,用来显示信息/错误信息的标签被隐藏:

    $("#<%=lblMessage.ClientID%>").hide();
    

    搜索关键字是从表单的文本字段中检索的。 如果有空白,它会被裁剪以删除:

    var sKeyword = $("#<%=txtKeyword.ClientID%>").val().trim();
    

    Web API 提供了两个GET方法:一个带参数,即GetCustomers()方法,另一个不带参数,即GetAllCustomers()方法。 GetCustomers()方法可以在api/customer/searchKeyword访问,而GetAllCustomers()方法可以在api/customer访问。

    因此,根据是否提供关键字,我们分别设置两个 uri,如下所示:

    var uri = ((sKeyword == "") ? "api/customer" : "api/customer/" + sKeyword);
    
  5. Now, we make the Ajax call to the Web API by sending a request to the URI set in the preceding code using the $.getJSON() method:

    $.getJSON(uri)
    

    返回对象为成功和不成功的请求分别提供了.done().fail()回调方法:

    .done(function (data){…})
    .fail(function (jqXHR, textStatus, errorThrown) {…});
    
  6. The preceding .done() callback method clears the result table by deleting all the rows except the header row:

    $("#tblResponse tr:gt(0)").remove();
    

    如果结果表不可见,则显示给用户:

    if ($("#tblResponse").is(":hidden"))
      $("#tblResponse").show();
    

    接下来,我们检查从 Web API 返回的数据对象的长度。 如果对象不为空,则打印每条记录,如下所示:

    if (data.length > 0){
      $.each(data, function (key, val) {
        $("#tblResponse").append("<tr><td>" + val.CustomerID + "</td><td>" + val.CompanyName + "</td><td>" + val.ContactName + "</td><td>" + val.Phone + "</td><td>" + val.Country + "</td></tr>");
      });
    }
    

    如果对象为空,只需向用户显示一条信息消息:

    $("#<%=lblMessage.ClientID%>").text("No results").show();
    
  7. .fail()回调方法中,显示jqXHR对象的statusstatusText参数如下:

参见 also

消费页面方法配方

对控制器动作进行 Ajax 调用

Ajax 调用也可以对 ASP 中的Controller动作进行。 净 MVC 应用。 在这个例子中,让我们从一个视图向控制器动作发送一个请求。 本例中使用的结构总结如下表:

|

构造

|

类型

|

描述

| | --- | --- | --- | | $("#identifier") | jQuery 选择器 | 这将根据元素的 ID 选择一个元素。 | | $.ajax() | jQuery 函数 | 这将向服务器发送一个带有设置选项的 Ajax 请求。 | | change | jQuery 的事件 | 当元素的值发生变化时,就会触发此操作。 它对应于 JavaScript 的change事件。 | | .on() | jQuery 事件绑定 | 这将一个或多个事件的事件处理程序附加到匹配的元素。 | | .text() | jQuery 方法 | 这将返回每个匹配元素的组合文本内容,或者设置每个匹配元素的文本内容。 | | .trim() | JavaScript 函数 | 这将删除字符串开头和结尾的空白。 | | .val() | jQuery 方法 | 返回第一个匹配元素的值,或者设置每个匹配元素的值。 |

准备

遵循以下步骤创建一个 MVC 应用,它将使用 Ajax 向控制器动作发布一个请求:

  1. Let's create a web page in ASP.NET MVC that returns the weather of a particular city. When the page is loaded, it displays a drop-down menu with a list of cities, as shown in the following screenshot:

    Getting ready

    当从下拉菜单中选择特定城市时,从Controller动作中检索天气信息并显示在页面上,如下图所示:

    Getting ready

  2. To create this application, launch an ASP.NET Web Application project in Visual Studio and name it Recipe6 (or any other suitable name). Select the Empty template and make sure that the MVC checkbox is selected, as shown in the following screenshot:

    Getting ready

  3. 点击OK按钮继续。

  4. 将 jQuery 库添加到项目中Scripts文件夹中。

  5. In the Solution Explorer tab, right-click on the Controllers folder and go to Add | Controller. From the Add Scaffold dialog box that is launched, choose MVC5 Controller – Empty, and click on the Add button:

    Getting ready

    在以下对话框中命名控制器HomeController,单击添加按钮:

    Getting ready

  6. In the code-behind file of HomeController, you will notice that, by default, an ActionResult method called Index is defined. Right-click on the Index method, and click on the Add View... menu option, as shown in the following screenshot:

    Getting ready

    这个将启动Add View窗口,如下面的截图所示。 为视图名称文本字段输入Index,选择空(无模型)模板。 取消选中Use a layout page选项,然后点击Add按钮:

    Getting ready

  7. 打开Index视图的代码后置文件并添加以下标记:

    <!DOCTYPE html>
    <html>
      <head>
        <meta name="viewport" content="width=device-width" />
        <title>City Weather</title>
        <script src="~/Scripts/jquery-2.1.4.js"></script>
        <style type="text/css">
          #divResult {
          font-variant: small-caps;
          color: blue;
          font-size: large;
          }
        </style>
      </head>
      <body>
        <form id="form1">
          <div>
            <h3>Please select the city to see the current weather:</h3>
            <select id="ddlCities">
              <option value="">--Please Select--</option>
              <option value="Dubai">Dubai</option>
              <option value="Hong Kong">Hong Kong</option>
              <option value="Mumbai">Mumbai</option>
              <option value="Perth">Perth</option>
              <option value="Singapore">Singapore</option>
              <option value="Wellington">Wellington</option>
            </select>
          </div>
          <br />
          <div id="divResult"></div>
        </form>
      </body>
    </html>
    
  8. Add a GetCityWeather()method to the code-behind file of HomeController to return the weather of a particular city. This method will take in one parameter, that is, the city name, and return a string containing the weather information.

    对于 VB,代码如下:

    Public Function GetCityWeather(ByVal sCity As String) As String
      Dim sWeather As String = String.Empty
      Select Case sCity
        Case "Dubai"
          sWeather = "Hot and sunny"
        Case "Hong Kong"
          sWeather = "Sunny"
        Case "Mumbai"
          sWeather = "Partially sunny"
        Case "Perth"
          sWeather = "Cloudy and windy"
        Case "Singapore"
          sWeather = "Hot and cloudy"
        Case "Wellington"
          sWeather = "Mostly cloudy"
        Case Else
          sWeather = "No weather information found"
      End Select
      Return sWeather
    End Function
    

    对于 c#,代码如下:

    public string GetCityWeather(string sCity)
    {
      string sWeather = String.Empty;
      switch (sCity)
      {
        case "Dubai": sWeather = "Hot and sunny";
          break;
        case "Hong Kong": sWeather = "Sunny";
          break;
        case "Mumbai": sWeather = "Partially sunny";
          break;
        case "Perth": sWeather = "Cloudy and windy";
          break;
        case "Singapore": sWeather = "Hot and cloudy";
          break;
        case "Wellington": sWeather = "Mostly cloudy";
          break;
        default: sWeather = "No weather information found";
          break;
      }
      return sWeather;
    }
    

    注意事项

    注意控制器动作接受字符串类型的sCity输入参数。 这个参数应该由 Ajax 请求中的客户机脚本提供。

怎么做……

将以下 jQuery 代码添加到视图的<script>块中:

<script type="text/javascript">
  $(document).ready(function() {
    $("#ddlCities").on("change", function() {
      $("#divResult").text("");
      var sCity = $(this).val().trim();
      if (sCity != "") {
        $.ajax({
          url: "/Home/GetCityWeather",
          type: "POST",
          data: '{ "sCity": "' + sCity + '"}',
          dataType: "text",
          contentType: "application/json; charset=utf-8",
          timeout: 5000,
          cache: false,
          success: function(response) {
            $("#divResult").text("The weather in " + sCity + " is " + response);
          },
          error: function(jqXHR, textStatus, errorThrown) {
            if (textStatus == "error") {
              alert("An error has occurred: " + jqXHR.status + " " + jqXHR.statusText);
            }
          }
        });
      }
    });
  });
</script>

How it works…

向控制器发送 Ajax 请求的操作如下:

  1. 元素div``divResult用于显示从控制器操作异步检索的天气信息。

  2. The Ajax request is posted when the selected item in the dropdown changes. Hence, an event handler is written to respond to the change event of the dropdown, as follows:

    $("#ddlCities").on("change", function () {…});
    

    在前面的事件处理程序中,首先清除div元素的内容:

    $("#divResult").text("");
    

    检索所选城市的名称。 白色空间,如果有,将被裁剪:

    var sCity = $(this).val().trim();
    

    如果城市名称不为空,则会向controller动作发送一个 Ajax 请求,如下所示:

    if (sCity != ""){
      $.ajax({
        url: "/Home/GetCityWeather",
        type: "POST",
        data: '{ "sCity": "' + sCity + '"}',
        dataType: "text",
        contentType: "application/json; charset=utf-8",
        timeout: 5000,
        cache: false,
        success: function (response) {
          $("#divResult").text("The weather in " + sCity + " is " + response);
        },
        error: function (jqXHR, textStatus, errorThrown) {
          if (textStatus == "error") {
            alert("An error has occurred: " + jqXHR.status + " " + jqXHR.statusText);
          }
        }
      });
    }
    

    在前面的 Ajax 调用中,设置了以下选项:

    • 请求 URL 设置为Controller/Action

    • HTTP 请求类型/方法设置为POST

    • 数据由一个 JSON 格式的字符串组成。 选择的城市以名称/值对的形式发送,以sCity作为名称,以下拉菜单中选择的值作为其值,如下:

      '{ "sCity": "' + sCity + '"}'
      
    • 响应的预期数据类型被设置为text,因为controller操作发送的天气信息是字符串格式。

    • 内容类型设置为application/json,字符设置为utf-8

    • 指定了一个5000毫秒的超时时间,以便如果服务器在此时间范围内未能响应,请求将终止。

    • 缓存被设置为false,因此响应不会缓存在浏览器中。

    • 为成功完成 Ajax 调用指定了一个回调函数。 该功能仅在div区域显示响应文本,如下所示:

    • 为不成功的 Ajax 调用指定一个回调函数。 在发生错误时,显示XmlHttpObjectstatusstatusText参数:

      function (jqXHR, textStatus, errorThrown) {
      	  if (textStatus == "error") {
      	    alert("An error has occurred: " + jqXHR.status + " " + jqXHR.statusText);
      	  }
      	}
      

参见 also

从 Web API 配方中检索数据

对 HTTP 处理程序进行 Ajax 调用

HTTP 处理程序是当请求特定资源时执行的进程。 例如,ASP.NET 提供了一个页面处理程序来处理*.aspx文件。 内建处理程序的另一个例子是用于处理*.asmx文件的 web 服务处理程序。

在这个配方中,让我们编写一个通用 HTTP 处理程序,它将向调用脚本返回自定义数据。 下表总结了本例中使用的结构:

|

构造

|

类型

|

描述

| | --- | --- | --- | | $("#identifier") | jQuery 选择器 | 这将根据其 ID 选择一个元素 | | $.ajax() | jQuery 函数 | 这将向服务器发送一个带有设置选项的 Ajax 请求 | | $.map() | jQuery 函数 | 这将数组或对象转换为另一个数组 | | .autocomplete() | jQuery UI 的方法 | 这将自动完成小部件附加到所需的元素 |

准备

遵循以下步骤构建一个页面,该页面将对 HTTP 处理程序进行 Ajax 调用:

  1. Let's create a web page that provides an autocomplete text field. The values in the autocomplete are filtered dynamically using the characters entered in the text field, as shown in the following screenshot:

    Getting ready

    注意,自动完成包含从 Northwind 数据库中的Customers表的Country列中检索到的国家列表。

  2. 要创建此应用,请启动ASP.NET Web 应用项目在 Visual Studio 中使用模板,并将其命名为Recipe7(或任何其他合适的名称)。

  3. Next, we will add a LINQ to SQL class to access data from the Customers table of the Northwind database. To do this, right-click on the project in Solution Explorer and go to Add | New Item. From the launched dialog box, select Data from the Installed templates from the left-hand side panel and LINQ to SQL classes from the middle panel. Name the item Northwind.dbml, and click on the Add button:

    Getting ready

  4. Connect to the Northwind database in Server Explorer and drag and drop the Customers table on Northwind.dbml, as shown in the following screenshot:

    Getting ready

  5. Next, we will add the HTTP handler to the project. So, right-click on the project in Solution Explorer and go to Add | New Item. From the dialog box, click on the Web tab from the Installed templates in the left-hand side panel and Generic Handler in the middle panel. Enter the name SearchKeys.ashx and click on the Add button:

    Getting ready

  6. In the code-behind file of the HTTP handler, add the following namespaces on the top.

    对于 VB,命名空间如下:

    Imports System.Data.Linq.SqlClient
    Imports System.Web.Script.Serialization
    

    对于 c#,命名空间如下所示:

    using System.Data.Linq.SqlClient;
    using System.Web.Script.Serialization;
    
  7. Update the SearchKeys class to include a ProcessRequest method, as follows.

    对于 VB,代码如下:

    Public Class SearchKeys
    Implements System.Web.IHttpHandler
    
    Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
      Dim strSearchText As String = context.Request.QueryString("sSearchText").Trim()
      Dim db As NorthwindDataContext = New NorthwindDataContext()
      Dim countryList As List(Of String) = (From cust In db.Customers
      Where SqlMethods.Like(cust.Country, "%" + strSearchText + "%")
      Select cust.Country).Distinct().ToList()
      Dim serializer As JavaScriptSerializer = New JavaScriptSerializer()
      Dim jsonString As String = serializer.Serialize(countryList)
      context.Response.Write(jsonString)
    End Sub
    
    ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
      Get
        Return False
      End Get
    End Property
    End Class
    

    对于 c#,代码如下:

    public class SearchKeys : IHttpHandler
    {
      public void ProcessRequest(HttpContext context)
      {
        string strSearchText = context.Request.QueryString["sSearchText"].Trim();
        NorthwindDataContext db = new NorthwindDataContext();
        List<string> countryList = (from cust in db.Customers
        where SqlMethods.Like(cust.Country, "%" + strSearchText + "%")
        select cust.Country).Distinct().ToList();
        JavaScriptSerializer serializer = new JavaScriptSerializer();
        string jsonString = serializer.Serialize(countryList);
        context.Response.Write(jsonString);
      }
    
      public bool IsReusable
      {
        get
        {
          return false;
        }
      }
    }
    

    注意事项

    在前面的代码中创建的 HTTP 处理程序实现了IHttpHander接口。 该接口要求处理程序实现IsReusable属性和ProcessRequest方法。 当调用处理程序时,将调用ProcessRequest方法。 因此,此方法包含生成必要输出的代码。 IsReusable属性表明IHttpHandlerFactory(即调用处理程序的对象)可以将处理程序放入池中,并从池中重用它,以提高性能。 如果将此属性设置为false,则每次调用该处理程序时都会创建一个新的处理程序。

    方法接受一个类型为HttpContext的参数。 使用Request.QueryString从该参数中提取搜索项。

    注意事项

    注意,客户机脚本需要将搜索关键字作为名称为sSearchText的查询字符串参数传递给处理程序。

    使用搜索关键字过滤Customers表中的国家列表。 然后使用JavaScriptSerializer类的Serialize方法将列表序列化为 JSON 字符串。

  8. Next, we will add the jQuery UI autocomplete widget to the project. To download this package using NuGet, from the menu at the top of the Visual Studio IDE, go to Project | Manage NuGet Packages. In the NuGet window, search for jQuery UI autocomplete, as shown in the following screenshot. Click on the Install button to install the package and its dependencies:

    Getting ready

    注意,安装完成后,会创建a Scripts文件夹,其中有一个文件列表,如下截图所示:

    Getting ready

    注意事项

    保留 jQuery 的下载版本,以确保与 jQuery UI 文件的兼容性。

  9. 将 web 表单添加到项目中,在head部分包含下载的脚本:

    <script src="Scripts/jquery-1.4.4.js"></script>
    <script src="Scripts/jquery.ui.core.js"></script>
    <script src="Scripts/jquery.ui.position.js"></script>
    <script src="Scripts/jquery.ui.widget.js"></script>
    <script src="Scripts/jquery.ui.autocomplete.js"></script>
    
  10. 在表单中添加以下标记:

```
<div>
  <h3>Autocomplete Search Box using AJAX</h3>
  <asp:Label ID="lblSearchText" runat="server" Text="Key in the search item:"></asp:Label>&nbsp;
  <asp:TextBox ID="txtSearchText" runat="server"></asp:TextBox>&nbsp;
  <asp:Button ID="btnSearch" runat="server" Text="Search" />
</div>
```
  1. 在头部部分包含 jQuery UI 样式表。 此样式表可以从https://jqueryui.com:
```
<link href="Styles/jquery-ui.css" rel="stylesheet" />
```

下载

怎么做……

添加以下 jQuery 代码到页面的<script>块:

<script type="text/javascript">
  $(document).ready(function() {
    $("#<%=txtSearchText.ClientID%>").autocomplete({
      source: function(request, response) {
        $.ajax({
          url: "SearchKeys.ashx?sSearchText=" + request.term,
          type: "POST",
          dataType: "json",
          contentType: "application/json; charset=utf-8",
          timeout: 5000,
          cache: false,
          success: function(data) {
            response($.map(data, function(item) {
              return {
                value: item
              }
            }));
          },
          error: function(jqXHR, textStatus, errorThrown) {
            if (textStatus == "error") {
              alert("An error has occurred: " + jqXHR.status + " " + jqXHR.statusText);
            }
          }
        });
      },
      minLength: 1
    });
  });
</script>

How it works…

Ajax 请求的发送到 HTTP 处理程序的工作方式如下:

  1. jQuery UI 自动完成小部件可以添加到接受输入的任何字段。 在本例中,小部件被添加到搜索文本字段,如下所示:

  2. The autocomplete() method provides a source option that can be set to an array, string, or function. In this case, we set the source to a function with two arguments, namely, a request object and a response callback.

    请求对象有一个term属性,该属性保存用户当前在该字段中键入的文本。 然后使用term属性作为查询字符串参数将 Ajax 请求发布到 HTTP 处理程序。 这个查询字符串参数被称为sSearchText,并在 HTTP 处理程序的ProcessRequest方法中检索:

    source:
    function(request,response){
      $.ajax({
        url: "SearchKeys.ashx?sSearchText=" + request.term,
        type: "POST",
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        timeout: 5000,
        cache: false,
        success: function (data) {
          response($.map(data, function (item)
          {
            return { value: item }
          }));
        },
        error: function (jqXHR, textStatus, errorThrown)
        {
          if (textStatus == "error") {
            alert("An error has occurred: " + jqXHR.status + " " + jqXHR.statusText);
          }
       }
      });
    },
    

    在前面的 Ajax 调用中,设置了以下选项:

    • 请求 URL 设置为URLOfHTTPHandler?QueryStringParam=Request.term

    • HTTP 请求的类型/方法设置为POST

    • 响应的预期数据类型设置为json

    • 内容类型设置为application/json,字符设置为utf-8

    • 指定了一个5000毫秒的超时时间,以便如果服务器在此时间范围内未能响应,请求将终止。

    • 缓存被设置为false,因此响应不会缓存在浏览器中。

    • 为成功完成 Ajax 调用指定了一个回调函数。 该函数将响应回调的参数设置为,建议用户使用$.map()函数,如下所示:

    • 为不成功的 Ajax 调用指定一个回调函数。 在发生错误时,显示XmlHttpObjectstatusstatusText参数:

      function (jqXHR, textStatus, errorThrown) {
      	  if (textStatus == "error") {
      	    alert("An error has occurred: " + jqXHR.status + " " + jqXHR.statusText);
      	  }
      	}
      
  3. 自动完成小部件还提供了minLength选项来设置用户在触发搜索之前需要输入的字符数。 在本例中,我们将minLength选项设置为1字符,如下所示:

参见 also

对控制器操作配方进行 Ajax 调用