
4.3 与Web Services结合
除了使用PageMethods输出静态函数供JavaScript调用外,ASP.NET AJAX也支持由JavaScript调用Web Service。用法很简单,只要在欲输出的Web Service类上标示ScriptService Attribute,再于ScriptManager的Services属性中设定URL即可。请依以下的步骤做。
1. 建立一个Web Service,命名为HelloService.asmx。
2. 在HelloService类中键入程序4-8的代码。
3. 建立一个新网页,命名为CallWebService.aspx。
4. 在页面上放入ScriptManager控件。
5. 在ScriptManager控件的Services属性窗中添加一个Service,如图4-3所示。

图4-3
6. 在网页的源码中键入程序4-9粗体字部分。
程序4-8
Samples\4\AjaxDemo2\App_Code\HelloService.cs using System; using System.Web; using System.Collections; using System.Web.Services; using System.Web.Services.Protocols; /// <summary> /// Summary description for HelloService /// </summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.Web.Script.Services.ScriptService] public class HelloService : System.Web.Services.WebService { public HelloService () { //Uncomment the following line if using designed components //InitializeComponent(); } [WebMethod] public string Hello(string name) { return string.Format("Hello {0}",name); } }
程序4-9
Samples\4\AjaxDemo2\CallWebServcie.aspx <%@ Page Language="C#" AutoEventWireup="true" CodeFile="CallWebService.aspx.cs" Inherits="CallWebService" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server"> <Services> <asp:ServiceReference Path="HelloService.asmx" /> <asp:ServiceReference Path="ZipServiceProxy.asmx" /> </Services> </asp:ScriptManager> <script language=javascript> function CallService() { var txt = $get('Text1'); HelloService.Hello(txt.value,SucceededCallback); } function SucceededCallback(result) { alert(result); } </script> </div> <input id="Text1" type="text" /> <input id="Button1" type="button" value="call" onclick= "CallService();" />/> </form> </body> </html>
完成后执行程序,点击call按钮,便可看到如图4-4所示的结果。

图4-4
这是如何办到的呢?先看程序4-9 中JavaScript的CallService函数,此函数调用了Hello-Service.Hello函数,HelloService对应了我们刚建立的HelloService.asmx这个Web Service,Visual Studio 2005建立Web Service时默认是不会加上任何namespace声明的,所以这里直接以<Web Service类名>.<函数名>便可调用Web Servcie,当你为Web Service类加上namespace之后,调用方式就得变成<namespace>.<Web Service类名>.<函数名>。JavaScript调用对应的Web Service函数时,除了传入该函数所需要的参数外(本例是name,字符串类型),还得传入另一个接收结果的函数(本例是OnSucceededCallback函数),这是因为ASP.NET AJAX调用Web Servcie时采用异步的方式调用,当调用完成后,便会调用所传入的接收结果函数,并传入传回值。OK,那ASP.NET AJAX是如何调用Web Service的呢?简单地说,ASP.NET AJAX替换了Web Service原有的处理机制,加上了一个特殊的参数/jsdebug,如果你在浏览器上键入Web Service的URL并加上/jsdebug参数时,就会得到ASP.NET AJAX为此Web Service所产生出来的Proxy程序文件,如图4-5所示。

图4-5
这个Proxy程序文件中声明了HelloService.Hello函数,并在此函数中利用ASP.NET AJAX Client Framework所提供的WebServiceProxy对象调用这个Web Service。在调用Web Service时,也可以像调用PageMethods时那样设定Timeout及错误处理机制,如程序4-10所示。
程序4-10
Samples\4\AjaxDemo2\CallWebServcie.aspx function CallService() { var txt = $get('Text1'); HelloService.set_timeout(5000); HelloService.Hello(txt.value,SucceededCallback,FailedCallback); } function SucceededCallback(result) { alert(result); } function FailedCallback(error) { alert("Call Service Error:"+error.get_message()); }
对Web Service有兴趣的读者或许会问一个问题,那就是在ASP.NET AJAX中,可否调用外部的Web Service呢?也就是于Service中将Path设为外部的网站,答案是可以的!不过有几个限制:第一、该Web Servcie必须也是以ASP.NET建立的,而且必须标示为ScriptService。二、受限于XMLHttpRequest不允许跨网域调用的限制,使用者必须调整浏览器的安全设定。第二个限制是比较麻烦且难以说服使用者的,所以最好的方式是自己建立一个Web Service,在此Web Service中串接外部的Web Service,这样不仅可以调用非ASP.NET所建立的Web Servcie,而且不受XMLHttpRequest不能跨网域的限制。
PageMethods与Web Service
在早期未Release的Atlas Framework中,并未要求PageMethods以静态函数类型声明,这使得每次Client端调用PageMethods时,都得经过传统的ASP.NET页面处理流程,因此让PageMethods背上效率不高的恶名。在ASP.NET AJAX正式版推出后,要求PageMethods一定得是静态函数,原因就是要绕过传统的ASP.NET页面处理流程,所以在ASP.NET AJAX正式版中,PageMethods已经与Web Service的性能不相上下了。另外,ASP.NET AJAX正式版中,你甚至可以将PageMethods当Web Servcie用,只要在ScriptManager控件的Services属性窗上添加Service时,将其Path设定为提供PageMethods的那个.aspx文件即可。