ASP.NET AJAX 调用 Web Service 与 WCF

介绍

1、通信
    使用 ASP.NET 可以创建可从网页中的客户端脚本访问的 Web 服务。页面与服务器通过 Web 服务通信层进行通信,该通信层使用 AJAX 技术进行 Web 服务调用。数据在客户端与服务器之间进行异步交换(通常采用 JSON 格式)。
2、元素
    在支持 AJAX 的网页中,浏览器向服务器发出对页面的初始请求,然后向 Web 服务发出对数据的后续异步请求。客户端通信元素采用代理类(从服务器下载)和核心客户端脚本库的形式。服务器通信元素是处理程序和自定义服务。下图显示了客户端与服务器之间的通信中涉及的元素。
3、AJAX 客户端结构
    浏览器使用代理类调用 Web 服务方法。代理类是由服务器自动生成并在页面加载时下载到浏览器中的脚本。代理类提供一个客户端对象,该对象表示某个 Web 服务的已公开方法。
      1.自定义服务代理类。这些类包含由服务器自动生成并下载到浏览器中的客户端脚本。代理类为页面中使用的每个 WCF 或 ASMX 服务提供一个对象。(也就是说,代理类为页面中 ScriptManager 控件的 ServiceReferences 元素中的每个项提供一个对象。)在客户端脚本中调用代理方法会创建一个对服务器上相应 Web 服务方法的异步请求。
      2.身份验证代理类。AuthenticationService 代理类由服务器身份验证应用程序服务生成。该代理类使得用户可以在浏览器中通过 JavaScript 进行登录或注销,而不必进行到服务器的往返过程。
      3.角色代理类。RoleService 代理类由服务器角色应用程序服务生成。使用该代理类可以通过 JavaScript 对用户进行分组并将每个组视为一个单元,而不必进行到服务器的往返过程。对于启用或拒绝对服务器上资源的访问,这可能十分有用。
      4.配置文件代理类。ProfileService 代理类由服务器配置文件应用程序服务生成。该代理类使得当前用户的配置文件信息通过 JavaScript 对客户端可用,而不必进行到服务器的往返过程。
      5.页面方法代理类。此代理类为客户端脚本提供脚本基础结构以调用 ASP.NET 页中的静态方法(就好像这些方法是 Web 服务方法一样)。有关更多信息,请参见从客户端脚本调用 Web 服务。
      6.Web 服务通信层。这是包含客户端脚本类型的库。这些类型使得浏览器(客户端)可以与服务器上的服务进行通信。这些类型还使客户端应用程序避免了在客户端与服务器之间建立和维护异步通信的复杂性。它们封装提供异步功能的浏览器 XMLHTTP 对象,并使得客户端应用程序可以独立于浏览器。Web 服务通信层的主要元素如下:
          WebRequest. 此元素提供用于发出 Web 请求的客户端脚本功能。
          WebRequestManager. 此元素管理由 WebRequest 对象向关联的执行器对象发出的 Web 请求流。类。
          XmlHttpExecutor. 此元素利用浏览器的 XMLHTTP 支持发出异步网络请求。类。
          JSON 序列化。将 JavaScript 对象序列化为 JSON 格式。使用 JavaScript eval 函数可进行反序列化。
      默认序列化格式为 JSON,但是 Web 服务和 ASP.NET 网页中的单个方法可以返回其他格式(如 XML)。可以通过属性来指定方法的序列化格式。

向客户端脚本公开 Web 服务

    使 Web 服务可从脚本访问
    为了使 Web 服务能够从脚本访问,该服务必须是使用 ScriptServiceAttribute 属性限定其 Web 服务类的 .asmx Web 服务。从脚本调用的各个方法必须使用 WebMethodAttribute 属性限定。
    示例代码:
  1. [ScriptService]
  2. public class SimpleWebService : System.Web.Services.WebService
  3. {
  4.     [WebMethod]
  5.     public string EchoInput(String input)
  6.     {
  7.         // Method code goes here.
  8.     }
  9. }

    向 ASP.NET 网页中的客户端脚本公开 Web 服务

    若要使 .asmx Web 服务能够从 ASP.NET 网页中的客户端脚本调用,必须向该网页添加一个 ScriptManager 控件。通过将 asp:ServiceReference 子元素添加到 ScriptManager 控件,然后将服务器引用 path 属性设置为 Web 服务的 URL,可以引用 Web 服务。ServiceReference 对象指示 ASP.NET 生成一个 JavaScript 代理类,用于从客户端脚本调用指定的 Web 服务。
    示例代码:
  1. <asp:ScriptManager runat="server" ID="scriptManager">
  2.   <Services>
  3.     <asp:ServiceReference
  4.        path="~/WebServices/SimpleWebService.asmx" />
  5.   </Services>
  6. </asp:ScriptManager>
    在 ASP.NET 网页中调用静态方法
可以将静态页方法添加到 ASP.NET 页中并将其用作 Web 方法。然后,无需创建单独的 .asmx 文件即可从该页中的脚本调用这些方法,就好像这些方法是 Web 服务的一部分。若要在页中创建 Web 方法,请导入 System.Web.Services 命名空间,然后将 WebMethodAttribute 属性添加到每个要公开的静态方法。页方法必须在执行页方法调用的页中进行定义。为了能够将静态页方法作为 Web 方法进行调用,必须将 ScriptManager 控件的 EnablePageMethods 属性设置为 true。
     使 WCF 服务可从客户端脚本访问
    若要使 WCF 服务可从客户端脚本进行访问,它必须满足下列要求:
    承载该服务的 Web 应用程序必须包含一个扩展名为 .svc 的文件。此文件包含指向 WCF 服务的 @ ServiceHost 指令。下面的示例演示了一个 @ ServiceHost 指令。
<%@ ServiceHost Language=C# Service="Aspnet.Samples.SimpleService" CodeBehind="~/App_Code/SimpleService.cs"%>
    必须将 Web 应用程序配置为支持从脚本调用 Web 服务。
    该服务必须是一个实现用 ServiceContractAttribute 标记的接口的类。要从脚本中调用的各个服务操作(方法)必须用 OperationContractAttribute 属性限定。
    示例代码:
  1. namespace Samples.Aspnet
  2. {
  3.     [ServiceContract(Namespace="MyServices.org")]
  4.     public interface ISimpleService
  5.     {
  6.         [OperationContract]
  7.         string HelloWorld1(string value1);
  8.         [OperationContract]
  9.         string HelloWorld2(DataContractType dataContractValue1);
  10.     }

  11.     [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
  12.     [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
  13.     public class SimpleService : ISimpleService
  14.     {
  15.         public SimpleService()
  16.         { }

  17.         public string HelloWorld1(string value1)
  18.         {
  19.             return "Hello " + value1;
  20.         }
  21.         public string HelloWorld2(DataContractType dataContractValue1)
  22.         {
  23.             return "Hello " + dataContractValue1.FirstName +
  24.                                 " " + dataContractValue1.LastName;
  25.         }
  26.     }

  27.     [DataContract]
  28.     public class DataContractType
  29.     {
  30.         string firstName;
  31.         string lastName;

  32.         [DataMember]
  33.         public string FirstName
  34.         {
  35.             get { return firstName; }
  36.             set { firstName = value; }
  37.         }
  38.         [DataMember]
  39.         public string LastName
  40.         {
  41.             get { return lastName; }
  42.             set { lastName = value; }
  43.         }
  44.     }

    

从 ASP.NET 网页的客户端脚本中使用 WCF 服务

    若要从 ASP.NET 网页的客户端脚本中调用 WCF 服务,必须先向该页面中添加一个 ScriptManager 控件。随后应以声明方式设置 ServiceReference 对象,方法是向 ScriptManager 控件添加一个 asp:ServiceReference 子元素并将其 path 属性设置为指向 WCF 服务。如:
    <asp:ServiceReference       Path="http://<serverhost>/SimpleService.svc"/>

调用 Web 服务方法

下面的示例演示如何进行以下类型的 Web 服务调用:
    调用没有返回值的 Web 服务。
    调用能够返回值的 Web 服务。
    调用带参数的 Web 服务方法。
    使用 HTTP GET 谓词调用 Web 服务方法。
    调用能够返回 XmlDocument 对象的 Web 服务方法。
示例代码:
  1. // This function calls the Web service method without 
  2. // passing the callback function. 
  3. function GetNoReturn()
  4. {
  5.     Samples.AspNet.WebService.GetServerTime();
  6.     alert("This method does not return a value.");
  7. }
  8. // This function calls the Web service method and 
  9. // passes the event callback function.  
  10. function GetTime()
  11. {
  12.     Samples.AspNet.WebService.GetServerTime(
  13.     SucceededCallback);
  14. }
  15. // This function calls the Web service method 
  16. // passing simple type parameters and the 
  17. // callback function  
  18. function Add(a,  b)
  19. {
  20.     Samples.AspNet.WebService.Add(a, b, 
  21.     SucceededCallback);
  22. }
  23. // This function calls the Web service method 
  24. // that returns an XmlDocument type.  
  25. function GetXmlDocument() 
  26. {
  27.     Samples.AspNet.WebService.GetXmlDocument(
  28.         SucceededCallbackWithContext, FailedCallback,
  29.         "XmlDocument")
  30. }
  31. // This function calls a Web service method that uses
  32. // GET to make the Web request.
  33. function MakeGetRequest() 
  34. {
  35.     Samples.AspNet.WebService.EchoStringAndDate(
  36.         new Date("1/1/2007"), " Happy",
  37.         SucceededCallback, 
  38.         FailedCallback, "HappyNewYear");
  39. }
  40. // This is the callback function invoked if the Web service
  41. // succeeded.
  42. // It accepts the result object, the user context, and the 
  43. // calling method name as parameters.
  44. function SucceededCallbackWithContext(result, userContext, methodName)
  45. {
  46.     var output;
  47.     // Page element to display feedback.
  48.     var RsltElem = document.getElementById("ResultId");
  49.     var readResult;
  50.     if (userContext == "XmlDocument")
  51.     {
  52.     
  53.         if (document.all) 
  54.             readResult = 
  55.                 result.documentElement.firstChild.text;
  56.         else
  57.             // Firefox
  58.            readResult =
  59.                 result.documentElement.firstChild.textContent;
  60.         
  61.          RsltElem.innerHTML = "XmlDocument content: " + readResult;
  62.     }
  63. }
  64. // This is the callback function invoked if the Web service
  65. // succeeded.
  66. // It accepts the result object as a parameter.
  67. function SucceededCallback(result, eventArgs)
  68. {
  69.     // Page element to display feedback.
  70.     var RsltElem = document.getElementById("ResultId");
  71.     RsltElem.innerHTML = result;
  72. }
  73. // This is the callback function invoked if the Web service
  74. // failed.
  75. // It accepts the error object as a parameter.
  76. function FailedCallback(error)
  77. {
  78.     // Display the error.    
  79.     var RsltElem = 
  80.         document.getElementById("ResultId");
  81.     RsltElem.innerHTML = 
  82.     "Service Error: " + error.get_message();
  83. }
  84. if (typeof(Sys) !== "undefined") Sys.Application.notifyScriptLoaded();

指定回调函数作为默认属性
    可以指定成功回调函数、失败回调函数和用户上下文,作为类的默认属性。然后,脚本可以调用代理类的 Web 服务方法,而无需传递这些值作为调用中的参数。
    MyNameSpace.MyService.set_defaultSucceededCallback(SucceededCallback);
    MyNameSpace.MyService.set_defaultFailedCallback(FailedCallback);
    MyNameSpace.MyService.set_defaultUserContext("my context");
    MyNameSpace.MyService.myServiceMethod(param1, param2);

处理 Web 服务方法调用中的错误

    为了捕捉错误,必须提供接受单个参数的失败回调函数。此参数将包含 Web 服务发送的错误对象。
下面的示例演示如何提供在 Web 服务方法调用过程中发生错误时调用的失败回调函数。
  1. // This is the failed callback function.
  2. function FailedCallback(error)
  3. {
  4.     var stackTrace = error.get_stackTrace();
  5.     var message = error.get_message();
  6.     var statusCode = error.get_statusCode();
  7.     var exceptionType = error.get_exceptionType();
  8.     var timedout = error.get_timedOut();

  9.     // Display the error.    
  10.     var RsltElem =
  11.         document.getElementById("Results");
  12.     RsltElem.innerHTML =
  13.         "Stack Trace: " +  stackTrace + "<br/>" +
  14.         "Service Error: " + message + "<br/>" +
  15.         "Status Code: " + statusCode + "<br/>" +
  16.         "Exception Type: " + exceptionType + "<br/>" +
  17.         "Timedout: " + timedout;
  18. }

从多个 Web 服务方法调用单个回调函数
    可以提供从多个 Web 服务方法调用的单个成功回调函数。为了使函数能够区分调用方,可以向函数传递用户上下文,也可以测试调用方法的名称。用户上下文和调用方法名称都可以在回调函数中使用。
    Samples.AspNet.WebService.Add(a, b, SucceededCallbackWithContext, FailedCallback);
    Samples.AspNet.WebService.Add(a, b, SucceededCallbackWithContext, FailedCallback, userContext, null);
    回调处理函数
  1. // This is the callback function called if the
  2. // Web service succeeded. It accepts the result
  3. // object, the user context, and the method name as
  4. // parameters.
  5. function SucceededCallbackWithContext(result, userContext, methodName)
  6. {
  7.     // It holds feedback message.
  8.     var output = "";
  9.     
  10.     // Page element to display the feedback message.    
  11.     var RsltElem =
  12.         document.getElementById("Results");
  13.     if (userContext)
  14.     {
  15.         output += "The user context is : " + userContext + "<br/>";
  16.         RsltElem.innerHTML =  output;
  17.         return;
  18.      }
  19.     if (methodName)
  20.         output += "The method name is : " + methodName + "<br/>";
  21.         
  22.       RsltElem.innerHTML =  output;
  23.      
  24. }
传递和返回复杂类型
    如果 Web 服务方法返回复杂类型,则成功回调函数所收到的返回值的形式是对应于服务器类型的 JavaScript 对象。
     1、使用自定类型
    在服务接口上使用[GenerateScriptType(typeof(类型))]属性。该类型的代理类将自动生成。这使客户端脚本能够创建类型的实例,并将其作为参数传递给方法调用。
    2、传递泛型或数组类型的参数
Web 服务方法可能支持泛型或 T 类型列表数组类型的参数或返回值。在这种情况下,ASP.NET 自动生成 T 类型的代理类以便用于客户端脚本。但是,如果泛型类型接受多个类型参数(例如 Dictionary<string, <T>>),则 ASP.NET 不会自动生成这些类型的代理类。为了使 ASP.NET 能够生成 T 类型的代理类,必须使用 T 类型的 GenerateScriptTypeAttribute 属性限定使用该类型的 Web 服务类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值