關於什麼是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的一些認識,若是有疑問,請與我交流!不正確的地方,望多指教!