思想决定人生,态度改变一切

成功者找方法,失败者找借口! 做事先做人;安分做人,本分做事!

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
二、客户端脚本直接访问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
单击显示全图,Ctrl+滚轮缩放图片


下面是修改后的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也是不可以的)。如果一切顺利,你将看到如下结果:(注意游览地址)
单击显示全图,Ctrl+滚轮缩放图片


以上是在客户端访问本地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>

运行结果:
单击显示全图,Ctrl+滚轮缩放图片


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

b、使用Web Service Bridge

asp.net ajax中Web Service桥的支持位于Futures CTP版本中,所以在使用之前,必须保证计算机安装了asp.net ajax 的Futures CTP版本。
单击显示全图,Ctrl+滚轮缩放图片


在网站的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桥文件的引用。

在城市名称中输入"深圳",下面是运行结果:
单击显示全图,Ctrl+滚轮缩放图片


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

原文出处:http://www.chenjiliang.com.cn/Article/View.aspx?ArticleID=4441&TypeID=85
posted on 2008-01-14 17:50  投石问路  阅读(629)  评论(0编辑  收藏  举报