關於什麼是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
using System; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class Service : System.Web.Services.WebService { public Service() { //若是使用設計的組件,請取消註釋如下行 //InitializeComponent(); } [WebMethod] public string HelloWorld() { return "Hello World"; } }
一個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特性的一些其它屬性: java
屬性 | 功能 | 示例 |
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)] |
咱們修改一下上述代碼。 web
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,請看代碼: 瀏覽器
public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { ServiceNamespace.Service ws = new ServiceNamespace.Service(); Response.Write(ws.Hello("Ruihua")); } }
你會看到,使用遠程方法就像使用本地方法同樣簡單,下面是運行結果:
緣由是:Web Service不容許咱們以匿名的方式訪問。你能夠在IIS信息服務中Web Service所在站點開啓這項功能。而後,你就能夠看到正確結果了:
方式二:使用WSDL工具。
咱們也可使用VS自帶的wsdl工具來實現相同的功能,這個工具能夠將wsdl文件生成在本地生成一個強類型的類文件,而後咱們能夠就能夠直接在項目中使用這個類文件,來訪問遠程資源。打開VS命令提供,輸入如下命令,以下圖所示:
同時在C:\Program Files\Microsoft Visual Studio 8\VC下會自動生成一個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 )] 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(Hello", RequestNamespace = 'javascript:void(0)', ResponseNamespace = 'javascript:void(0)', 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])); } } }