您的位置:首页 > 编程语言 > ASP

使用ASP.NET AJAX异步调用Web Service和页面中的类方法(1):调用Web Service、调用页面中的类方法

2013-04-28 08:23 961 查看
转载自:/article/4589370.html

调用WebService

之所以ASP.NETAJAX将WebService提高到了如此的重要位置上,让它几乎成为了ASP.NETAJAX服务器端逻辑最受推荐的实现方式,是因为WebService天生就是纯粹为了业务逻辑而设计的。我们都知道,WebService没有提供什么“花哨”的用户界面,而是心无旁骛地专注于程序逻辑上的实现,这恰好和ASP.NETAJAX客户端编程模型所倡导的“将表现层和业务逻辑层彻底分开”的理念不谋而合——客户端的ASP.NETAJAX框架用来处理程序所有的界面、与用户交互功能,服务器端则仅仅提供纯粹的数据,不涉及任何表现样式。

借助于ASP.NETAJAX异步通讯层所自动生成的WebService客户端访问代理,在表现层代码,也就是JavaScript中调用WebService获取数据成为了一件异常简单的事情——其表现出的优雅甚至让我们不敢相信:难道Ajax程序也能写得这么简单?

接下来就让我们通过一个简单的示例程序了解一下在ASP.NETAJAX应用程序中使用JavaScript异步调用WebService的方法。出于演示的目的,程序的功能非常简单:用户在页面的文本框中输入名字,然后点击旁边的按钮,如图3-1所示。



图3-1用户在界面中输入自己的名字

程序将借助ASP.NETAJAX异步通讯层以Ajax方式把用户的名字发送至服务器端的WebService。随后该WebService在服务器端根据用户的名字生成一段问候信息并发送回客户端,客户端收到服务器响应之后,将把这段问候信息显示出来,如图3-2所示。



图3-2程序显示出来自服务器的问候信息

让我们先从服务器端的WebService入手。新建一个名为SimpleWebService的WebService类并在其中声明一个普通的WebService方法——SayHello()。该方法将接受一个名为name的参数,并生成一条问候信息返回:

[WebService(Namespace="http://tempuri.org/")]

[code][WebServiceBinding(ConformsTo=WsiProfiles.BasicProfile1_1)]
publicclassSimpleWebService:System.Web.Services.WebService

{
[WebMethod]

publicstringSayHello(stringname)

{

returnstring.Format("Hello{0}!",name);

}

}

[/code]
这就是个普通的WebService,没有任何不一样之处。注意不要忘记为SayHello()方法添加[WebMethod]属性,这是每个Web方法都必需的。

为了让ASP.NETAJAX生成该WebService的客户端异步调用代理,进而允许我们在JavaScript代码中直接调用该方法,我们还要再为SimpleWebService类添加[ScriptService]属性,这一部分才是ASP.NETAJAX为WebService提供的附加功能(注意代码中粗体部分):

//…………

[code][ScriptService]
//…………

publicclassSimpleWebService:System.Web.Services.WebService

{

//…………

}

[/code]
提示:我们也可以直接为需要暴露给客户端的WebService方法添加[ScriptService]属性,而不必将其添加到WebService类上。

[ScriptService]属性位于System.Web.Script.Services命名空间中,如果需要的话,还要添加如下的using语句:

usingSystem.Web.Script.Services;


下面列出完整的SimpleWebServiceWebService代码如下,注意其中粗体部分:

usingSystem;

[code]usingSystem.Web;
usingSystem.Web.Services;

usingSystem.Web.Services.Protocols;
usingSystem.Web.Script.Services;

[WebService(Namespace="http://tempuri.org/")]

[WebServiceBinding(ConformsTo=WsiProfiles.BasicProfile1_1)]

[ScriptService]

publicclassSimpleWebService:System.Web.Services.WebService

{
[WebMethod]

publicstringSayHello(stringname)

{

returnstring.Format("Hello{0}!",name);

}

}

[/code]
完成了WebService编写之后,我们来先行测试一下——开发过程中不断地进行阶段性测试有助于尽快发现潜在的问题,并将其扼杀在萌芽中。如果一切顺利的话,那么测试该WebService时可以看到如图3-3所示的结果。



图3-3测试WebService时的界面

接下来即可用ASP.NETAJAX异步调用这个WebService了。首先新建一个ASP.NET页面。当然,该页面所在的Web站点必须已经配置好了ASP.NETAJAX的支持,详细配置方法请参考本书第I卷。在该页面上添加一个ScriptManager服务器端控件,这是每一个ASP.NETAJAX应用程序都必不可少的:


<asp:ScriptManagerID="sm"runat="server">

[code]</asp:ScriptManager>
[/code]
为了让ASP.NETAJAX为前面的WebService生成客户端异步调用代理,我们需要在ScriptManager控件中添加该WebService的引用:


<asp:ScriptManagerID="sm"runat="server">

[code]<Services>
<asp:ServiceReferencePath="Services/SimpleWebService.asmx"/>

</Services>

</asp:ScriptManager>

[/code]
这种声明语法隐约中传递了这样的含义:WebService的客户端异步调用代理脚本将由ScriptManager控件管理——这非常自然,不是么?ScriptManager就是用来管理(manage)脚本(script)的呀!关于<Services/>标签以及<asp:ServiceReference/>标签的详细使用方法,在本书第I卷中已经有详细讨论,这里不赘。

随后声明程序界面中必不可少的UI元素:


<inputid="tbName"type="text"/>

[code]<inputid="btnInvoke"type="button"value="SayHello"
onclick="returnbtnInvoke_onclick()"/>

<divid="result"></div>

[/code]
其中id为tbName的<input/>作为文本框,用来让用户输入名字;id为btnInvoke的<input/>作为按钮,点击将触发异步调用WebService;id为result的<div/>则用来将WebService返回的问候内容显示出来。这些id均将在稍后用到。

上面代码中btnInvoke按钮定义了click事件的事件处理函数,该函数的实现如下。注意这是客户端JavaScript代码:


functionbtnInvoke_onclick(){

[code]vartheName=$get("tbName").value;
SimpleWebService.SayHello(theName,onSayHelloSucceeded);

}

[/code]
首先用$get("tbName").value取得了用户在文本框中输入的文字。然后第二句SimpleWebService.SayHello()即调用了ASP.NETAJAX异步通讯层自动为SimpleWebService生成的客户端代理。这是本示例程序中最为重要的一句——与用C#在WebService中声明的SayHello()方法签名相比,其参数个数以及顺序均完全一样,甚至调用语法也没什么特别——都是[NameSpace].[ClassName].[MethodName](param1,param2…,callbackFunction)。由此我们能够看出ASP.NETAJAX异步通讯层为降低开发者学习曲线、提高开发者生产效率所做出的努力及良苦用心。

参考:关于用来取得DOM元素引用的$get()方法,请参考本卷第1章中的介绍。

不过客户端代理还提供了额外的一个参数——异步调用的回调函数名称,这里为onSayHelloSucceeded。该回调函数将在服务器端异步调用成功返回后由ASP.NETAJAX异步通讯层自动调用。onSayHelloSucceeded()回调函数的代码如下:


functiononSayHelloSucceeded(result){

[code]$get("result").innerHTML=result;
}

[/code]
onSayHelloSucceeded()回调函数的result参数代表了本次异步调用的返回结果,即WebService方法的返回值,这里即为包含了用户名字的问候语。该回调函数将由ASP.NETAJAX异步通讯层自动调用,其result参数也会由ASP.NETAJAX异步通讯层传递进来,无需我们任何手工控制。在本示例程序的onSayHelloSucceeded()回调函数中,我们只是简单地将这句问候语显示在id为result的<div/>中。

参考:ASP.NETAJAX异步通讯层为WebService自动生成的客户端代理以及相应的回调函数还提供了更多的参数和配置功能,这些都将在本章中详细介绍。

这样就完成了本示例程序的所有代码编写。运行该程序,如果一切顺利的话,你将看到如图3-1和图3-2所示的界面。

ASP.NETAJAX的异步通讯层在本示例程序中小试牛刀,纵观整个示例程序的实现代码,我们不难看出该架构的强大功能以及为我们开发者细心周全的考虑。虽然在实际开发中,我们很难遇到本示例程序中这样简单的功能。但麻雀虽小,五脏俱全,理解了这样一个简单的示例程序之后,我们完全可以举一反三,根据开发过程中的实际需要编写不同的WebService以及客户端调用代码,轻松地完成工作。

总结:想要使用ASP.NETAJAX在客户端JavaScript中异步调用服务器端WebService,我们需要:

为WebService类或需要暴露给客户端的WebService方法添加[ScriptService]属性;

为WebService中需要暴露给客户端的方法添加[WebMethod]属性;

在页面中的ScriptManager控件中添加对该WebService的引用;

在客户端使用如下JavaScript语法调用该WebService:
[NameSpace].[ClassName].[MethodName](param1,param2......,callbackFunction)

为客户端异步调用指定回调函数,在回调函数中接收返回值并进一步处理。

3.2调用页面中的类方法

让客户端JavaScript直接能够异步调用到服务器端的WebService,这看起来真的是个不错的主意——理想化的分层Ajax应用程序就应该这样嘛!不过作为被ASP.NET服务器端开发模型“宠坏”了的我们,更加熟悉的方法是直接将方法写在ASP.NET页面中,比如处理页面中的某个服务器端按钮Click事件的代码,就可能这样调用定义在同一张页面代码文件中的方法:


protectedvoidButton1_Click(objectsender,EventArgse)

[code]{
myLabel.Text=this.GetTextForLabel();

}


publicstringGetTextForLabel()

{

//......

return"SomeText";

}

[/code]
对于那些“遗留”的ASP.NET应用程序来讲,这样直接定义在ASP.NET页面中的方法更是相当常见。若是仅仅为了配合ASP.NETAJAX的客户端访问WebService功能,就将这些方法一一迁移到WebService中,岂不是非常麻烦?

好在ASP.NETAJAX在设计时考虑到了这个问题,并提供给我们一种作为替代的选择。ASP.NETAJAX异步通讯层能够将声明在ASP.NET页面中的公有的类方法(C#中的static,VB.NET中的Shared)当作WebService中声明的方法一样对待,为其生成类似的客户端调用代理。

我们还是通过一个实例程序来了解这个功能。该示例程序的功能与界面均与前面一节中的完全一致,唯一的不同就是,客户端异步调用的不再是某个WebService,而是定义在ASP.NET页面中的类方法。

首先是定义在ASP.NET页面中的类方法,完整的方法声明如下:

[WebMethod]

[code]publicstaticstringSayHelloFromPage(stringname)
{

returnstring.Format("Hello{0}!",name);

}

[/code]
特别需要注意的是,若要让ASP.NETAJAX为其生成客户端调用代理,那么一定要为该方法添加[WebMethod]属性。

然后是ScriptManager控件,注意粗体部分代码设置了EnablePageMethods属性为true,这也是让客户端能够直接调用服务器端页面方法所必需的。若你忘记了设定该属性,那么程序将无法完成预期功能:


<asp:ScriptManagerID="sm"EnablePageMethods="true"runat="server"/>


程序界面中的UI元素和前一个节中的示例程序完全一致,这里不赘:


<inputid="tbName"type="text"/>

[code]<inputid="btnInvoke"type="button"value="SayHello"
onclick="returnbtnInvoke_onclick()"/>

<divid="result"></div>

[/code]
而本示例程序中按钮的click事件处理函数以及异步调用的回调函数则需要一定的修改,如下所示:


functionbtnInvoke_onclick(){

[code]vartheName=$get("tbName").value;
PageMethods.SayHelloFromPage(theName,onSayHelloSucceeded);

}


functiononSayHelloSucceeded(result){

$get("result").innerHTML=result;

}

[/code]
注意上述代码中的粗体部分。可以看到,调用页面方法代理时统一的前缀为PageMethods。接下来是页面方法的名称,这里为SayHelloFromPage(),其参数列表和C#中方法的定义一致,额外的一个参数表示本次异步调用的回调函数。即语法为:


PageMethods.[MethodName](param1,param2…,callbackFunction);


这样即完成了本示例程序,运行一下,我们将会看到如图3-1和图3-2一样的界面。

总结:想要使用ASP.NETAJAX在客户端JavaScript中异步调用定义在ASP.NET页面中的方法,我们需要:

将该方法声明为公有(public);

将该方法声明为类方法(C#中的static,VB.NET中的Shared),而不是实例方法;

为该方法添加[WebMethod]属性;

将页面中ScriptManager控件的EnablePageMethods属性设置为true;

在客户端使用如下JavaScript语法调用该页面方法:
PageMethods.[MethodName](param1,param2…,callbackFunction);

为客户端异步调用指定回调函数,在回调函数中接收返回值并进一步处理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐