学会使用Web Service下(客户端访问)

二、客户端脚本直接访问Web Service 

借助于asp.net ajax异步通信层自动生成的客户端代理,我们也可以在客户端JS中使用与服务器端同样的语法调用定义在服务器端的Web Service的方法!下面我们分两种情况来分析:


1、客户端直接调用本地Web Service

默认情况下,asp.net Web Service并没有提供直接通过客户端脚本进行访问的方式,为了实现这个功能,我们必须借助于asp.net ajax框架,它为我们提供了使用JS直接调用本地Web Service完善的支持,所以对于以下的操作,你必须确保已安装了asp.net ajax框架。下面让我们看看具体如何实现:

(1)、新建一个asp.net ajax Web站点,然后添加一个Web Service



下面是修改后的Web Service代码:

复制   保存
<%@ WebService Language="C#" Class="WebService" %>

using System;

using System.Web;

using System.Web.Services;

using System.Web.Services.Protocols;

[WebService(Namespace = "http://ruihua.cnblogs.com/")]

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

[System.Web.Script.Services.ScriptService]

public class WebService  : System.Web.Services.WebService {

[WebMethod]

public string Hello(string name)

{

return string.Format("Hello,{0}!Current Time is :{1}", name, DateTime.Now.ToString());

}

}


请注意红色部分,要想使客户端能够访问到Web Service,我们必须为类添加ScriptService特性(当然,你也可以直接添加到相应的方法上)。这个特性是在asp.net ajax框架的Extension部分定义的。好了,Web Service就已经写好了,下面看看如何在客户端调用。

b、新建一个asp.net ajax站点,修改后的前台代码如下所示:

复制   保存
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

<title>Untitled Page</title>

<script type="text/javascript">

function pageLoad(sender,args)

{

//注意引用方式

            WebService.Hello("Ruihua",onCompleted);

}

//异步调用后执行的回调函数

        function onCompleted(result)

{

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

}

</script>

</head>

<body>

<form id="form1" runat="server">

<asp:ScriptManager ID="ScriptManager1" runat="server">

<Services>

<asp:ServiceReference Path="http://localhost/WebServiceForJS/WebService.asmx" />

</Services>

</asp:ScriptManager>

<div id="result"></div>

</form>

</body>

</html>


代码非常简单,我们只需在ScriptManager中添加对Web Service文件的引用,然后在客户端脚本中使用[NameSpace].[ClassName].[MethodName][para1,para2,...,callbackFunction]的方式直接调用即可,然后在回调函数中接收值并进一步处理。(注意,测试过程中,请将站点都设置为Web共享,这样在引用Web Service的时候就不必考虑到端口号,因为对于同域内不同端口的访问JS也是不可以的)。如果一切顺利,你将看到如下结果:(注意游览地址)



以上是在客户端访问本地Web Service的情况,下面让我们看看客户端如何访问远程Web Service.


2、客户端访问远程Web Service

出于安全性考虑,客户端JS脚本是不可以直接访问远程Web Service的,若想实现这个功能,则必须在本地服务器端提供一个代理,透过这个代理进行访问。下面我们以访问http://www.webxml.com.cn/WebServices/WeatherWebService.asmx为例来说明。具体可采取以下两种方式:

a、通过本地Web Service中转

实现思路:服务器端建立一个Web Service,然后在相应的方法中调用远程Web Service的方法,客户端脚本直接访问本地Web Service中方法。

主要代码:

复制   保存
<%@ WebService Language="C#" Class="WebService" %>

using System;

using System.Web;

using System.Web.Services;

using System.Web.Services.Protocols;

[WebService(Namespace = "http://ruihua.cnblogs.com/")]

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

[System.Web.Script.Services.ScriptService]

public class WebService  : System.Web.Services.WebService {

[WebMethod]

public string[] GetWeatherbyCityName(string theCityName)

{

WeatherForcast.WeatherWebService ws = new WeatherForcast.WeatherWebService();

return ws.getWeatherbyCityName(theCityName);

}

}


前台Default.aspx代码:

复制   保存
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

<title>Untitled Page</title>

<script type="text/javascript">

function btnGetWeather_onclick(sender,args)

{

var cityName=$get("tbCityName").value;

WebService.GetWeatherbyCityName(cityName,onCompleted,onFailed);

}

//异步调用后成功后执行的回调函数

        function onCompleted(result)

{

var str = new Sys.StringBuilder();

for(var i=0;i<result.length;i++)

{

str.append(result[i]);

str.append("<br/>");

}

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

}

//异步调用后失败后执行的回调函数

        function onFailed(error)

{

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

}

</script>

</head>

<body>

<form id="form1" runat="server">

<asp:ScriptManager ID="ScriptManager1" runat="server">

<Services>

<asp:ServiceReference Path="WebService.asmx" />

</Services>

</asp:ScriptManager>

<label id="lblCityName">Please input CityName:</label>

<input id="tbCityName" type="text" />

<input id="btnGetWeather" type="button" value="Get Weather" onclick="return btnGetWeather_onclick()" />

<div id="result"></div>

</form>

</body>

</html>


运行结果:



下载本示例  
http://files.cnblogs.com/ruihua/webserviceforjs1.rar

b、使用Web Service Bridge

asp.net ajax中Web Service桥的支持位于Futures CTP版本中,所以在使用之前,必须保证计算机安装了asp.net ajax 的Futures CTP版本。



在网站的Bridges目录下新建一个WeatherForcase.asbx的XML文件,内容如下:

复制   保存
<?xml version="1.0" encoding="utf-8" ?>

<bridge namespace="Ruihua" className="WeatherForcast">

<proxy type="Microsoft.Web.Preview.Services.BridgeRestProxy" serviceUrl="http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getWeatherbyCityName"/>

<method name="getWeatherbyCityName">

<input>

<parameter name="theCityName"/>

</input>

</method>

</bridge>


我们来看一下.asbx文件各标签:
(1)<Bridge/>:定义该本地代理的命名空间(namespace属性)和类名(className属性)。这两个属性是代表客户端调用时使用的命名空间及类名,与远程Web Service我关。
(2)<proxy/>:声明该代理的类型,并指定远程Web Service的URL属性。注意这里的URL属性值的构成:.asmx文件的URL加斜杆和要调用的方法名。
(3)<method/>:定义了远程Web Service中要调用的方法名称及参数,注意name属性应与远程Web Service中要调用的方法名称一致。
(4)该标签中通过<parameter/>子标签声明了方法的参数。

有几点需要特别说明一下:
(1)、我在实际使用过程中发现,web Service桥只支持httpGet协议,所以我们需要在Web.config文件中开启HttpGet方式(默认为HttpPost)。在<configuration/><system.web/>下添加如下配置:

复制   保存
<webServices>

<protocols>

<add name="HttpGet"/>

</protocols>

</webServices>


(2)如果你使用Futures CTP版本自带的模板新建了一个支持Web Service桥的站点,你需要手动将<buildProviders>节下的<add>元素的extension属性中的"*"号去掉,这是Fetures CTP的Bug。
(3)一个Web Service桥文件中仅能代理一个方法,如果你需要访问多个方法,则需要新建多个Web Service桥。如你在其中写了多个<proxy>及<method/>,客户端调用时也只会执行最先的那个代理对应的方法。暂时没还没找到其它好的方法。
(4)不能使用asp.net ajax异步通信层的服务器端至客户端的类型转换功能,因此我们在客户端得到的返回类型只能是string类型,从而加大了进一步进行处理的难度。

由于存在以上限制,个人感觉使用web Service桥不如使用本地Web Service中转方便,或许是asp.net ajax在这方面还不够成熟吧!

下面是Default.aspx的内容:

复制   保存
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

<title>Untitled Page</title>

<script type="text/javascript">

function btnGetWeather_onclick(sender,args)

{

var cityName=$get("tbCityName").value;

Ruihua.WeatherForcast.getWeatherbyCityName({"theCityName":cityName},onCompleted,onFailed);

}

//异步调用后成功后执行的回调函数

        function onCompleted(result)

{

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

}

//异步调用后失败后执行的回调函数

        function onFailed(error)

{

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

}

</script>

</head>

<body>

<form id="form1" runat="server">

<asp:ScriptManager ID="ScriptManager1" runat="server">

<Services>

<asp:ServiceReference Path="Bridges/WeatherForcase.asbx" />

</Services>

</asp:ScriptManager>

<label id="lblCityName">Please input CityName:</label>

<input id="tbCityName" type="text" />

<input id="btnGetWeather" type="button" value="Get Weather" onclick="return btnGetWeather_onclick()" />

<div id="result"></div>

</form>

</body>

</html>


以上有两点需要特别注意:
(1)调用远程Web方法的参数的书写方式是采用JSON方式,各个参数需要显式指明参数名和值,并包装为一个JS对象整体传入本地代理方法,这与常规调用方式有所不同。
(2)在ScriptManager中添加的是对Web Service桥文件的引用。

在城市名称中输入"深圳",下面是运行结果:



下载本示例
http://files.cnblogs.com/ruihua/usewebservicebridge.rar

你可能感兴趣的:(web Service)