关于什么是Web Service,相信在不少地方都会有介绍。简单的讲,Web Service就是为Web应用程序之间彼此共享资源提供了一种可能。采起的方式是将相应的类及其中的方法暴露出来,而后调用者就能够直接调用这些类中的 方法,达到访问远程资源的目的。本文只是想告诉,若是去使用Web Service。我主要从服务器端访问Web Service、客户端访问Web Service两方面来介绍。若是你还不会使用Web Service,但愿对你有所帮助。
1、服务器端访问Web Service
这也是Web Service最适宜的调用环境。咱们只需知道一个远程Web Service的URL,而后咱们就能够直接使用Wsdl工具或更方便的添加Web 引用的方法,将远程Web Service(指.asmx文件)中对应类生成一个强类型的本地化代理。经过这个代理,咱们就能够像使用本地方法同样,去调用这个远程类中的方法。使用 的过程是很是的简单。下面让咱们看看具体的操做。
一、新建一个Web Service

选择asp.net Web服务模板,而后你会看到VS已经自动为咱们生成了一个Web Service的示例代码。javascript
一个Web Service的主要部分VS已经帮咱们写好了。这里有几个地方,我大概说一下。[WebService(Namespace = http://tempuri.org/)]特 性部分,它声明了Web Service所对应的XMl文件的命名空间,若是你直接浏览Web Service文件,它会出如今XML文件的命名空间声明中。仍是建议修改一下Namespace,虽然它只是一个URI。[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]特性声称的是本Web Service所应符合的Web服务互操做性规范,通常状况下咱们无需考虑这个,只有某些操做与这个规范不相符的时候,咱们就须要修改ConformsTo = WsiProfiles.None。(好比BasicProfile1_1规范并不支持方法的重载,若是你有重载方法的话,就须要修改它。)须要特别说明 的是,一般一个web Service文件对应的只有一个类,固然并非说你不能够在一个.asmx文件中写多个类,但只有与WebService指令中的className值 对应的那个类才会被公开。而对于类中的方法,咱们必须显式加上[WebMthod]特性,才能被公开,这点与类不一样。让咱们看一下WebMethod特性 的一些其它属性:
html
属性java |
功能web |
示例ajax |
BufferResponse |
设置为True时,XML Web服务的响应就保存在内存中,并发送为一个完整的包。若是该属性设置为False,则响应在服务器上构造的同时,会发送给客户机。 |
[WebMethod(BufferResponse=true)] |
CacheDuration |
指定响应在系统的高速缓存中的保存时间(秒),默认值为0,表示禁用高速缓存。把XML Web服务的响应放在高速缓存中,会提升Web服务的性能。 |
[WebMethod(BufferResponse=true, CacheDuration=30)] |
Description |
对在XML Web服务的测试页面上显示的Web Method应用文本的描述。 |
[WebMethod(Description="该方法用于获取一个简单的字符串")]编程 |
EnableSession |
设置为True时,会激活Web Method的会话状态,其默认值为False。 |
[WebMethod(EnableSession=true)] |
MessageName |
给Method指定一个惟一的名称,若是要使用重载的Web Method,则必须指定。 |
[WebMethod(MessageName="Method1")] |
TransactionOption |
为Web Method指定事务的支持,其默认值为Disbled。若是Web Method是启动事务的根对象,Web服务就能够用另外一个须要事务处理的WebMethod参与事务处理。其值能够是NotSupported、 Supported、Required和RequiresNew。 |
[WebMethod(TransactionOption =System.EnterpriseServices. TransactionOption.Supported)] |
咱们修改一下上述代码。浏览器
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.None)]
public class Service : System.Web.Services.WebService


{
public Service ()

{

}

[WebMethod]

public string Hello(string name)
{
return string.Format("Hello,{0}!Current Time is :{1}", name, DateTime.Now.ToString());
}
}
程序很简单,传进去一个姓名,返回一串提供信息,下面咱们来看一下如何使用这个Web Service.
二、访问Web Service
首先须要说明一下,为什么咱们可以在本地服务器上访问到远程服务器的Web Service?不管是使用添加Web引用的方式仍是使用Wsdl工具,最终的结果都是生成了一个远程Web Service中类的强类型化本地代理。而后咱们是经过这个代理来实现访问远程资源访问的。下面咱们看看怎么经过这两种方式来实现。
首先咱们新建一个新的Web应用程序
方式一:使用添加Web 引用。在解决方案资源管理器中单击右键,选择添加Web 引用...,以下所示:

在URL部分你能够直接输入远程Web Service的URL,固然若是引用的Web Service来自本地,你能够单击相应的连接,而后进行选择。在Web引用名中,填入你自定义的名称。注意,这个名称就代指Web Service的命名空间。在访问的时候,咱们必须经过这个名称才能引用到Web Service中的类。填好后,单击添加引用便可。

为了保证本地测试方便,请将Web Service所在网站设为Web 共享,这样咱们就没必要考虑在Web引用中加入端口号才能访问的问题。添加Web引用对话框中查找的实际是WSDL文件,Microsoft的XML Web服务会根据.asmx文件自动生成wdsl文件。固然,咱们也能够根据.asmx文件在浏览器中打开wsdl文件,按以下路径:
http://localhost/WebService/Service.asmx?wsdl
接下来,你会看到VS已经为咱们添加好了Web 引用。

同时在Web.Config文件中也包含了对Web服务的引用,以下所示:
<appSettings>
<add key="ServiceNamespace.Service" value="http://localhost/WebService/Service.asmx"/>
</appSettings>
接下来,让咱们看一下如何使用这个Web Service,请看代码:缓存
你会看到,使用远程方法就像使用本地方法同样简单,下面是运行结果:

缘由是:Web Service不容许咱们以匿名的方式访问。你能够在IIS信息服务中Web Service所在站点开启这项功能。而后,你就能够看到正确结果了:

方式二:使用WSDL工具。
咱们也可使用VS自带的wsdl工具来实现相同的功能,这个工具能够将wsdl文件生成在本地生成一个强类型的类文件,而后咱们能够就能够直接在项目中使用这个类文件,来访问远程资源。打开VS命令提供,输入如下命令,以下图所示:

同时在C:\Program Files\Microsoft Visual Studio 8\VC下会自动生成一个Service.cs的文件。咱们将这个文件置于咱们的项目中,就能够直接使用了。安全

自动生成的Service.cs代码:
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行库版本:2.0.50727.42
//
// 对此文件的更改可能会致使不正确的行为,而且若是
// 从新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Serialization;

//
// 此源代码由 wsdl 自动生成, Version=2.0.50727.42。
//



/**//// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(Name="ServiceSoap", Namespace="http://ruihua.cnblogs.com/")]

public partial class Service : System.Web.Services.Protocols.SoapHttpClientProtocol
{
private System.Threading.SendOrPostCallback HelloOperationCompleted;

/**//// <remarks/>

public Service()
{
this.Url = "http://localhost/WebService/Service.asmx";
}

/**//// <remarks/>
public event HelloCompletedEventHandler HelloCompleted;

/**//// <remarks/>
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://ruihua.cnblogs.com/Hello", RequestNamespace="http://ruihua.cnblogs.com/", ResponseNamespace="http://ruihua.cnblogs.com/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]

public string Hello(string name)
{

object[] results = this.Invoke("Hello", new object[]
{
name});
return ((string)(results[0]));
}

/**//// <remarks/>

public System.IAsyncResult BeginHello(string name, System.AsyncCallback callback, object asyncState)
{

return this.BeginInvoke("Hello", new object[]
{
name}, callback, asyncState);
}

/**//// <remarks/>

public string EndHello(System.IAsyncResult asyncResult)
{
object[] results = this.EndInvoke(asyncResult);
return ((string)(results[0]));
}

/**//// <remarks/>

public void HelloAsync(string name)
{
this.HelloAsync(name, null);
}

/**//// <remarks/>

public void HelloAsync(string name, object userState)
{

if ((this.HelloOperationCompleted == null))
{
this.HelloOperationCompleted = new System.Threading.SendOrPostCallback(this.OnHelloOperationCompleted);
}

this.InvokeAsync("Hello", new object[]
{
name}, this.HelloOperationCompleted, userState);
}

private void OnHelloOperationCompleted(object arg)
{

if ((this.HelloCompleted != null))
{
System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
this.HelloCompleted(this, new HelloCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
}
}

/**//// <remarks/>

public new void CancelAsync(object userState)
{
base.CancelAsync(userState);
}
}


/**//// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
public delegate void HelloCompletedEventHandler(object sender, HelloCompletedEventArgs e);


/**//// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]

public partial class HelloCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
{
private object[] results;
internal HelloCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :

base(exception, cancelled, userState)
{
this.results = results;
}

/**//// <remarks/>

public string Result
{

get
{
this.RaiseExceptionIfNecessary();
return ((string)(this.results[0]));
}
}
}
至此,服务器端访问Web Service就到这里,下面让咱们来看看客户端如何该问Web Service。
下一篇:学会使用Web Service下(客户端访问)
服务器
2、客户端脚本直接访问Web Service
借助于asp.net ajax异步通讯层自动生成的客户端代理,咱们也能够在客户端JS中使用与服务器端一样的语法调用定义在服务器端的Web Service的方法!下面咱们分两种状况来分析:
一、客户端直接调用本地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.
二、客户端访问远程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 = 'javascript:void(0)')]

[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>
运行结果:

下载本示例
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的内容:
以上有两点须要特别注意:
(1)调用远程Web方法的参数的书写方式是采用JSON方式,各个参数须要显式指明参数名和值,并包装为一个JS对象总体传入本地代理方法,这与常规调用方式有所不一样。
(2)在ScriptManager中添加的是对Web Service桥文件的引用。
在城市名称中输入"深圳",下面是运行结果:

下载本示例以上内容仅是我我的在学习Web Service的一些认识,若是有疑问,请与我交流!不正确的地方,望多指教!