关于什么是Web Service,相信在很多地方都会有介绍。简单的讲,Web Service就是为Web应用程序之间彼此共享资源提供了一种可能。采取的方式是将相应的类及其中
的方法暴露出来,然后调用者就可以直接调用这些类中的方法,达到访问远程资源的目的。本文只是想告诉,如果去使用Web Service。我主要从服务器端访问Web Service、客户端访问Web Service两方面来介绍。如果你还不会使用Web Service,希望对你有所帮助。
一、服务器端访问Web Service
这
也是Web Service最适宜的调用环境。我们只需知道一个远程Web Service的URL,然后我们就可以直接使用Wsdl工具或更方便的添加Web 引用的方法,将
远程Web Service(指.asmx文件)中对应类生成一个强类型的本地化代理。通过这个代理,我们就可以
像使用本地方法一样,去调用这个远程类中的方法。使用的过程是非常的简单。下面让我们看看具体的操作。
1、新建一个Web Service
选择asp.net Web服务模板,然后你会看到VS已经自动为我们生成了一个Web Service的示例代码。
复制 保存
using System; using System.Web; using System.Web.Services; using System.Web.Services.Protocols;
[WebService(Namespace = "http:///")] [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:///)]
特性部分,它声明了Web Service所对应的XMl文件的命名空间,如果你直接浏览Web Service文件,它会出现在XML文件的命名空间声明中。还是建议修改一下Namespace,
虽然它只是一个URI。比如你可以把它改为Namespace=http://ruihua.cnblogs.com/。[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
特性声称的是本Web Service所应符合的Web服务互操作性规范,一般情况下我们无需考虑这个,只有某些操作与这个
规范不相符的时候,我们就需要修改ConformsTo = WsiProfiles.None。(比如BasicProfile1_1规范并不支持方法
的重载,如果你有重载方法的话,就需要修改它。)需要特别说明的是,通常一个web Service文件对应的只有一个类,当然并不是说你不可以在一个.asmx文件中写多个类,但只有
与WebService指令中的className值对应的那个类才会被公开。而对于类中的方法,我们必须显式加上[WebMthod]特性,才能被公
开,这点与类不同。让我们看一下WebMethod特性的一些其它属性:
属性 |
功能 |
示例 |
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:///")] [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.
2、访问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的文件。我们将这个文件置于我们
的项目中,就可以直接使用了。
复制 保存
Microsoft(R) Web Services 描述语言实用工具 [Microsoft (R) .NET Framework, Version 2.0.50727.42]
Copyright (C) Microsoft Corporation. All rights reserv
wsdl.exe -
使用 ASP.NET,根据 WSDL 协定文件、XSD 架构和 .disc 发现文档,
为 Xml Web Services 客户端和 Xml Web Ser 代码的实用工具。此工具可以与 disco.exe 一起使
用。
wsdl.exe <选项> <URL 或路径> <URL 或路径>
- 选
项 -
<URL 或路径> - 指向 WSDL 协定、XSD 架构或 .discomap 文档
的 URL 或
/nologo 取消显示版权标志。
/language:<language>
用于生成的代理类的语言。请从“CS”、“VB”、“JS” “CPP”中选择,或者为实
现 System.CodeDom.Compiler. 的类提供一个完全限定的名称。默认语言为“CS”(CShar 缩
写形式为“/l:”。
/sharetypes 打开类型共享功能。此功能针对不同服务之间共享 的相
同类型(命名空间、名称和网络签名必须相同) 创建一个具有单一类型定义的代码文件。 请使
用 http:// URLs 作为命令行参数来引用 服务,或为本地文件创建一个 discomap 文档。
/verbose
指定 /sharetypes 开关时显示额外信息。 缩写形式为“/v”。
/fields 生
成字段而非属性。缩写形式为“/f”。
/order 为粒子成员生成显式顺序标识符。
/enableDataBinding
在所有生成的类型上实现 INotifyPropertyChanged 接口 以启用数据绑定。缩写形式为
“/edb”。
/namespace:<namespace> 生成的代理或模板的命名空间。默认命名空
间 为全局命名空间。缩写形式为“/n:”。
/out:<fileName|directoryPath>
生成的代理代码的文件名或目录路径。默认文件名是从 服务名派生的。缩写形式为“/o:”。
/protocol:<protocol>
重写要实现的默认协议。请从“SOAP”、“SOAP12”、 “HttpGet”、“HttpPost”中选择。
/username:<username>
/password:<password> /domain:<domain> 连接到要求
身份验证的服务器时使用的凭据。 缩写形式为“/u:”、“/p:”和“/d:”。
/proxy:<url>
用来处理 HTTP 请求的代理服务器的 URL。 默认为使用系统代理服务器设置。
/proxyusername:<username>
/proxypassword:<password> /proxydomain:<domain> 连
接到要求身份验证的代理服务器时使用的凭据。 缩写形式为“/pu:”、“/pp:”和“/pd:”。
/appsettingurlkey:<key>
在代码生成中用来读取 URL 属性的 默认值的配置项。默认为不从配置 文件中读取。缩写形式为
“/urlkey:”。
/appsettingbaseurl:<baseurl> 计算 URL 段时
使用的基 URL。 还必须指定 appsettingurlkey 选项。URL 段是 从 appsettingbaseurl 计
算 WSDL 文档中的 URL 的相对 URL 的结果。缩写形式为“
/parsableerrors 输
出错误,其格式与编译器报告的格式类似。
- 高级 -
/server 服务器开关已被否
决。请改用 /serverInterface。 使用基于协定的 ASP.NET,为 Xml Web Services 实现生成抽
象类。默认情况下,生成 客户端代理类。
/serverInterface 为 ASP.Net Web 服
务的服务器端实现生成接口。将为 wsdl 文档中的每个绑定生成 一个接口。wsdl 单独实现 wsdl 协定(实现接口的类在类方
法上不应包括下列任意一项: 更改 wsdl 协定的 Web 服务属性或序列化属性)。缩写形式为“/si”。
/parameters:<file>
从指定的 xml 文件读取命令行选项。这样可以指定命令行中无法使用的选项,例如选择 生成的异步编程模型类型。有
关详细信息,请参阅工具文档。缩写形式为“/par:”。
复制 保存
//------------------------------------------------------------------------------ // <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])); } } }
|