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

ASP.NET 3.5、AJAX 和 Web 服务

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.67/5 (5投票s)

2008年3月18日

CPOL

6分钟阅读

viewsIcon

62302

downloadIcon

1252

本文介绍如何使用 AJAX 客户端脚本调用 Web Service 方法。

引言

本文介绍在 ASP.NET 3.5 AJAX 环境中使用 Web 服务,以及如何从客户端 JavaScript 调用 Web 服务方法。它还概述了新的 System.Web.Script 命名空间,并探讨了定义 Web 服务方法客户端调用的方法。

在 AJAX 中调用 Web Service 方法

为了改善 Web 用户体验,ASP.NET 的 AJAX 功能在其新版本中包含了从客户端 JavaScript 调用 Web 服务方法的新方法。AJAX 允许您在不提交或渲染整个页面的情况下,调用服务器端方法而无需回发。客户端脚本可以向 Web 方法发出请求,并将数据作为输入参数传递给方法;数据也可以从服务器发送回客户端浏览器。

为了使您的应用程序能够通过客户端脚本调用 ASP.NET Web 服务,服务器异步通信层会自动生成 JavaScript 代理类。为每个 Web 服务生成一个代理类,前提是在页面中的 <asp:ScriptManager> 控件下包含一个 <asp:ServiceReference> 元素。

<asp:ScriptManager runat="server" ID="scriptManagerId">
     <Services>
            <asp:ServiceReference  Path="WebService.asmx" />
     </Services>
</asp:ScriptManager>

此代理类在页面加载时下载到浏览器,并提供一个客户端对象,该对象代表 Web 服务公开的方法。要调用 Web 服务的方法,请调用生成的 JavaScript 代理类的相应方法。代理类进而与 Web 服务通信。请求通过浏览器的 XMLHTTP 对象异步发出。

<asp:ScriptReference> 元素用于注册将在网页中使用的 JavaScript 文件。只有在注册了 CallWebServiceMethod.js 文件后,才能在其上调用方法。

从脚本调用 Web 服务方法是异步的。要获取返回值或确定请求何时返回,您必须提供一个成功回调函数。当请求成功完成时,将调用回调函数,并且它包含 Web 方法调用的返回值(如果有)。您还可以提供一个失败回调函数来处理错误。此外,您可以传递用户上下文信息以供回调函数使用。

JSONJavaScript Object Notation 是客户端-服务器请求之间数据转换使用的默认序列化格式。您可以禁用所有当前启用的协议,如 HTTP-GET、HTTP-POST,甚至早期 Web 服务形式中使用的 XML-SOAP 格式。Web.Config 文件中的以下设置将执行相同的操作。

<system.web>
    <webServices>
        <protocols>
          <clear/>
        </protocols>
      </webServices> 
</system.web>

下图详细展示了客户端和服务器端不同的层。对 Web 服务方法的请求会经过这些层。您可以看到如何调用一个可用代理对象上的方法,以及 Web 请求如何由客户端浏览器端的 XmlHttp 对象处理。在服务器端,您的请求像往常一样由 HTTP 处理程序处理,并发送进行 XML/JSON 序列化。

ajax-client-server-architecture.jpg

示例:在 AJAX 中使用 Web Service 方法

在 AJAX 中使用 Web Service 方法涉及两个步骤。第一步是创建和定义 Web 服务的方式略有不同。第二步是从页面使用客户端脚本调用服务方法。

步骤 1:创建 Web Service

System.Web.Scripts.Services 命名空间中,您可能会找到一个名为“ScriptSrvice”的属性类,需要将其应用于 Web 服务类,以便客户端脚本可以调用 Web 服务方法。这将使代理生成脚本能够生成与 Web 服务类对应的代理对象。

同样,在相同的命名空间中,您可能会找到另一个名为“ScriptMethod”的属性类,在将其应用于 Web 方法后,您可以指定用于调用方法的 HTTP 动词和响应格式。此属性有三个参数,如下所述:

  • UseHttpGet:将其设置为 true 将使用 HTTP GET 命令调用方法。默认值为 false
  • ResponseFormat:指定响应是序列化为 JSON 还是 XML。默认值为 JSON。
  • XmlSerializeString:指定是否将所有返回类型(包括字符串类型)序列化为 XML。当响应序列化为 JSON 时,将忽略 XmlSerializeString 属性的值。

好的…现在,使用 Visual Studio 2008 中的 ASP.NET Web 服务模板创建一个新的网站,并按如下方式修改 Web 服务类:

using System.Web.Script.Services;
namespace AjaxWebService
{ 

   [WebService(Namespace = "https://:49232/AjaxWebService/")]
   [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 
   [ScriptService]
   public class Service : System.Web.Services.WebService 
   {
    string myXmlData = @"<?xml version=""1.0"" encoding=""utf-8"" ?> 
            <Book> 
            <Title>Programming ASP.NET 3.5, AJAX and Web Services</Title> 
            </Book>"; 
    // This method uses JSON response formatting 
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)] 
    [WebMethod] 
    public string getNextBackupDate(int months) 
    { 
        return DateTime.Now.AddMonths(months).ToShortDateString(); 
    } // This method uses XML response formatting 
    [ScriptMethod(ResponseFormat = ResponseFormat.Xml)] 
    [WebMethod] 
    public string Greetings(string name) 
    public XmlDocument GetBookTitle() 
    { 
        XmlDocument xmlDoc = new XmlDocument(); 
        xmlDoc.LoadXml(myXmlData); 
        return xmlDoc; 
    } 
    // This method uses HTTP-GET protocol to call it 
    [ScriptMethod(UseHttpGet = true)] 
    [WebMethod] 
        public string HelloWorld() 
        { 
            return "Hello, world"; 
        } 
    } 
}

注意:默认情况下,使用 ScriptService 启用的 Web 服务不会在浏览器中进行测试。您需要按如下方式修改 Web.Config 文件中的设置才能测试上述 Web 服务。

<webServices>
  <protocols> 
    <add name="HttpGet"/> 
    <add name="HttpPost"/> 
    </protocols> 
</webServices>

步骤 2:使用客户端脚本调用 Web Service 方法

ASP.NET Web 服务方法可以从客户端脚本异步调用,而无需回发且无需刷新整个页面。只有数据会在服务器和客户端浏览器之间传输。

目前,.NET framework 3.5 支持同一域(同一网站)中的 Web 服务和客户端网页。您不能使用 VS2008 Beta 2 调用位于 Internet 或任何其他系统上的 Web 服务方法。

现在,向现有 Web 服务项目添加一个新的“启用 AJAX 的网页”,并按如下标记中的指定,向网页添加控件:

编写 JavaScript 函数来调用 Web 服务方法和回调方法。通过使用代理类,并按顺序传递参数列表、成功回调函数的名称、失败回调函数的名称以及用户上下文,来调用 Web 服务方法。

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>AJAX Web Form</title>
    <script type="text/javascript">

    function CallNextDate() 
    {
        AjaxWebService.Service.getNextBackupDate(1, OnSucceeded);
    }

    function CallHelloWorld() 
    {
        AjaxWebService.Service.HelloWorld(OnSucceeded);
    }

    function CallBookTitle() 
    {
        AjaxWebService.Service.GetBookTitle(OnSuccess, OnFail, 
                               "XmlDocument");
    }

    // This is the callback function that processes
    // the Web Service return value in JSON format.
    function OnSucceeded(result)
    {
        var myresult = document.getElementById("Text1");
        myresult.value = result;
    }

    // This is the callback function that processes
    // the Web Service return value in XML format.
    function OnSuccess(result)
    {
        var myresult = document.getElementById("Text1");
        myresult.value = "Title: " + result.documentElement.text;
    }

    // This is the callback function that processes
    // the Web Service return value in XML format.
    function OnFail(error)
    {
        var myresult = document.getElementById("Text1");
        myresult.value = "Service Error: " + error.get_message();
    }
    </script>
    <style type="text/css">
        #Text1
        {
            width: 375px;
        }
        #Button2
        {
            width: 140px;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server">
        <Services>
        <asp:ServiceReference Path="~/Service.asmx"/>
        </Services>
        </asp:ScriptManager>
        <br />
        Result:           <input id="Text1" type="text" /><br />
        <br />
        <input id="Button1" type="button" 
             value="Get Server Time" onclick="CallNextDate()" />
        <input id="Button2" type="button" 
             value="Say Hello World" onclick="CallHelloWorld()" />
        <input id="Button3" type="button" 
             value="Get Book Title" onclick="CallBookTitle()" />
        <br />
        <br />
        <br />
        </div>
    </form>
</body>
</html>

在上​​面的标记中,请注意 ScriptManager 控件的 ServiceReference 元素中的 path 属性如何指向 Web 服务类。这使得 Web 服务方法可以从 default.aspx 页面的脚本中调用。内联函数 CallNextDateCallHelloWorldCallBookTitle 用于调用三个 Web 服务方法。OnSuccessOnFail 方法是回调方法,当 Web 服务方法执行完成后就会执行。

您的网页布局大致如下所示:

AjaxWebPageLayout.jpg

为了使客户端网页能够正常工作,您需要在 Web.Config 文件中添加以下设置:

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="System.Web.Extensions" 
              publicKeyToken="31bf3856ad364e35"/>
      <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
    </dependentAssembly>
    <dependentAssembly>
      <assemblyIdentity name="System.Web.Extensions.Design" 
                 publicKeyToken="31bf3856ad364e35"/>
      <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
    </dependentAssembly>
  </assemblyBinding>
</runtime>

这将指示 ASP.NET 引擎加载当前版本的 System.Web.Extensions.dll 和其他 DLL,以利用 ASP.NET 3.5 中内置的 AJAX 支持。

结论

ASP.NET 3.5 及其内置的 AJAX 客户端-服务器框架增强了使用客户端脚本调用 Web 服务方法的功能。当您使用 Visual Studio 2008 时,大多数设置和 JavaScript 代码文件都会自动加载。在早期版本的 AJAX、ATLAS 中调用 Web 服务方法会遇到一些麻烦,使得开发和调试有些困难。现在,借助 ASP.NET 3.5,它已成为更简单、更熟悉的 VS2008 IDE 的固有组成部分。

© . All rights reserved.