WebService Interface

WebService Interface? 什么东西? 为什么要这个玩意儿,它有什么用?

有这样一种情况: 我有一个Client程序,要引用到多个Web Service,这一些Web Service的调用方式是一样的,只是各自Web Service本身的实现有一些区别.那么,对于Client来说,最好的调用方式就是这样的:

IObj obj  =   new  WebService1();
obj.Invoke();

obj 
=   new  WebService2();
obj.Invoke();

即通常说到的基于Interface的编程...

但是Web Service的实现和普通的Interface又有一些不同.下面是一个例子,记录了如何使用Web Service Interface.

1. 创建一个接口 ICalculate ,加上WebServiceBinding这个Attribute,指明这个Web Service的Name和Namespace:

    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1,Name = " ICalculate " ,Namespace = " http://dev.robinzhong.com/ICalculate/ " )]
    
public   interface  ICalculate
    
{
        [WebMethod]
        
int Add(int a, int b);
        
        [WebMethod]
        
int Sub(int a, int b);
    }

2. 创建一个实现了上述接口的类 XCalculate ,代码如下:

    [WebService(Namespace  =   " http://tempuri.org/XCalculate/ " )]
    [WebServiceBinding(ConformsTo 
=  WsiProfiles.BasicProfile1_1,Name = " ICalculate " ,Namespace = " http://dev.robinzhong.com/ICalculate/ " )]
    [ToolboxItem(
false )]
    
public   class  XCalculate : System.Web.Services.WebService,ICalculate
    
{
        
public int Add( int a, int b )
        
{
            
throw new NotImplementedException( );
        }


        
public int Sub( int a, int b )
        
{
            
throw new NotImplementedException( );
        }

    }


这个地方,不用实现的代码.写这两个东西的目的,是为了得到WSDL的定义,注:仅仅只是此SOAP消息的定义,和具体的Service无关.
访问此Web Service地址,得到其WSLD文件 ( http://localhost:2839/XCalculate.asmx?wsdl ).删除 <wsdl :service />节点.
得到下面的WSDL文件:

<  ?xml  version ="1.0"  encoding ="utf-8" ? >
< wsdl  :definitions xmlns:soap ="http://schemas.xmlsoap.org/wsdl/soap/"  xmlns:tm ="http://microsoft.com/wsdl/mime/textMatching/"  xmlns:soapenc ="http://schemas.xmlsoap.org/soap/encoding/"  xmlns:mime ="http://schemas.xmlsoap.org/wsdl/mime/"  xmlns:tns ="http://dev.robinzhong.com/ICalculate/"  xmlns:s ="http://www.w3.org/2001/XMLSchema"  xmlns:soap12 ="http://schemas.xmlsoap.org/wsdl/soap12/"  xmlns:http ="http://schemas.xmlsoap.org/wsdl/http/"  targetNamespace ="http://dev.robinzhong.com/ICalculate/"  xmlns:wsdl ="http://schemas.xmlsoap.org/wsdl/" >
  
</ wsdl >< wsdl  :types >
    
< :schema elementFormDefault ="qualified"  targetNamespace ="http://dev.robinzhong.com/ICalculate/" >
      
</ s >< :element name ="Add" >
        
</ s >< :complexType >
          
</ s >< :sequence >
            
< :element minOccurs ="1"  maxOccurs ="1"  name ="a"  type ="s:int"   />
            
< :element minOccurs ="1"  maxOccurs ="1"  name ="b"  type ="s:int"   />
          
</ s >
        
      
      
< :element name ="AddResponse" >
        
</ s >< :complexType >
          
</ s >< :sequence >
            
< :element minOccurs ="1"  maxOccurs ="1"  name ="AddResult"  type ="s:int"   />
          
</ s >
        
      
      
< :element name ="Sub" >
        
</ s >< :complexType >
          
</ s >< :sequence >
            
< :element minOccurs ="1"  maxOccurs ="1"  name ="a"  type ="s:int"   />
            
< :element minOccurs ="1"  maxOccurs ="1"  name ="b"  type ="s:int"   />
          
</ s >
        
      
      
< :element name ="SubResponse" >
        
</ s >< :complexType >
          
</ s >< :sequence >
            
< :element minOccurs ="1"  maxOccurs ="1"  name ="SubResult"  type ="s:int"   />
          
</ s >
        
      
    
  
</ wsdl >
  
< wsdl  :message name ="AddSoapIn" >
    
< wsdl  :part name ="parameters"  element ="tns:Add"   />
  
</ wsdl >
  
< wsdl  :message name ="AddSoapOut" >
    
< wsdl  :part name ="parameters"  element ="tns:AddResponse"   />
  
</ wsdl >
  
< wsdl  :message name ="SubSoapIn" >
    
< wsdl  :part name ="parameters"  element ="tns:Sub"   />
  
</ wsdl >
  
< wsdl  :message name ="SubSoapOut" >
    
< wsdl  :part name ="parameters"  element ="tns:SubResponse"   />
  
</ wsdl >
  
< wsdl  :portType name ="ICalculate" >
    
</ wsdl >< wsdl  :operation name ="Add" >
      
< wsdl  :input message ="tns:AddSoapIn"   />
      
< wsdl  :output message ="tns:AddSoapOut"   />
    
</ wsdl >
    
< wsdl  :operation name ="Sub" >
      
< wsdl  :input message ="tns:SubSoapIn"   />
      
< wsdl  :output message ="tns:SubSoapOut"   />
    
</ wsdl >
  
  
< wsdl  :binding name ="ICalculate"  type ="tns:ICalculate" >
    
< soap  :binding transport ="http://schemas.xmlsoap.org/soap/http"   />
    
</ wsdl >< wsdl  :operation name ="Add" >
      
< soap  :operation soapAction ="http://dev.robinzhong.com/ICalculate/Add"  style ="document"   />
      
</ wsdl >< wsdl  :input >
        
< soap  :body use ="literal"   />
      
</ wsdl >
      
< wsdl  :output >
        
< soap  :body use ="literal"   />
      
</ wsdl >
    
    
< wsdl  :operation name ="Sub" >
      
< soap  :operation soapAction ="http://dev.robinzhong.com/ICalculate/Sub"  style ="document"   />
      
</ wsdl >< wsdl  :input >
        
< soap  :body use ="literal"   />
      
</ wsdl >
      
< wsdl  :output >
        
< soap  :body use ="literal"   />
      
</ wsdl >
    
  
  
< wsdl  :binding name ="ICalculate1"  type ="tns:ICalculate" >
    
< soap12  :binding transport ="http://schemas.xmlsoap.org/soap/http"   />
    
</ wsdl >< wsdl  :operation name ="Add" >
      
< soap12  :operation soapAction ="http://dev.robinzhong.com/ICalculate/Add"  style ="document"   />
      
</ wsdl >< wsdl  :input >
        
< soap12  :body use ="literal"   />
      
</ wsdl >
      
< wsdl  :output >
        
< soap12  :body use ="literal"   />
      
</ wsdl >
    
    
< wsdl  :operation name ="Sub" >
      
< soap12  :operation soapAction ="http://dev.robinzhong.com/ICalculate/Sub"  style ="document"   />
      
</ wsdl >< wsdl  :input >
        
< soap12  :body use ="literal"   />
      
</ wsdl >
      
< wsdl  :output >
        
< soap12  :body use ="literal"   />
      
</ wsdl >


得到了Soap消息的定义和结构,我们就可以用wsdl.exe来生成代码,开始实际的编程工作了.

3. 调用 wsdl.exe /l:cs /n:xxx /out:xxx.cs /si icalculate.wsdl ,注意这个/si,完整的参数是 /serverInterface.
生成的代码如下:

    [System.CodeDom.Compiler.GeneratedCodeAttribute( " wsdl " " 2.0.50727.42 " )]
    [System.Web.Services.WebServiceBindingAttribute(Name
= " ICalculate " , Namespace = " http://dev.robinzhong.com/ICalculate/ " )]
    
public   interface  IICalculate  {
        
        
/// <remarks />
        [System.Web.Services.WebMethodAttribute()]
        [System.Web.Services.Protocols.SoapDocumentMethodAttribute(
"http://dev.robinzhong.com/ICalculate/Add", RequestNamespace="http://dev.robinzhong.com/ICalculate/", ResponseNamespace="http://dev.robinzhong.com/ICalculate/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
        
int Add(int a, int b);
        
        
/// <remarks />
        [System.Web.Services.WebMethodAttribute()]
        [System.Web.Services.Protocols.SoapDocumentMethodAttribute(
"http://dev.robinzhong.com/ICalculate/Sub", RequestNamespace="http://dev.robinzhong.com/ICalculate/", ResponseNamespace="http://dev.robinzhong.com/ICalculate/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
        
int Sub(int a, int b);
    }

注意: 生成的是一个Interface,不是具体的类.这个Interface,就是我所谓的Web Service Interface (其实实质就是WSDL定义).这个Interface的定义和前面定义的ICalculate,除了多一些Attribute外,其它的一模一样.这些个Attribute就是最大的区别,用来定义WebService调用时接收/发送的Soap消息.

4. 即然Interface都出来了.那么这个时候可以写真正的Web Service了,以下是两个Web Service的示例代码:

    [WebService(Namespace  =   " http://tempuri.org/ " )]
    [WebServiceBinding(ConformsTo 
=  WsiProfiles.BasicProfile1_1,Namespace = " http://dev.robinzhong.com/ICalculate/ " ,Name = " ICalculate " ,Location = " http://localhost/WSInterface/ICalculate.wsdl " )]
    [ToolboxItem(
false )]
    
public   class  NewCalculate : System.Web.Services.WebService ,IICalculate
    
{

        [WebMethod]
        
public int Add( int a, int b )
        
{
            
return a + b;
        }


        [WebMethod]
        
public int Sub( int a, int b )
        
{
            
return a - b;
        }

    }

 

    [WebService(Namespace  =   " http://tempuri.org/ " )]
    [WebServiceBinding(ConformsTo 
=  WsiProfiles.BasicProfile1_1,Name = " ICalculate " ,Namespace = " http://dev.robinzhong.com/ICalculate/ " ,Location = " http://localhost/WSInterface/ICalculate.wsdl " )]
    [ToolboxItem(
false )]
    
public   class  SimpleCalculate : System.Web.Services.WebService, IICalculate
    
{
        
public int Add( int a, int b )
        
{
            
return a + b;
        }


        
public int Sub( int a, int b )
        
{
            
return a - b;
        }

    }

注意WebServiceBinding这个Attribute,在这两个Web Service类中,都使用了这个Attribute,而且设置其Name="ICalculate", Namespace="http://dev.robinzhong.com/ICalculate"... <font color=red>(注:由于IICalculate接口已定义了WebServiceBindingAttribute,所以在其继承的类中也不必定义此Attribute,ASP.NET 2.0测试通过.)</font>

5. Web Service已写好,下面就是Client的调用代码.同样的,也得先生成IICalculate这个接口,同样的方法.
  wsdl.exe /l:cs /n:xxx /out:xxx.cs /si icalculate.wsdl

得到IICalcuate接口.
然后再添加上面两个Web Service中任意一个WebService的引用.比如NewCalculate这个Web Service,得到如下代码:

[System.CodeDom.Compiler.GeneratedCodeAttribute( " System.Web.Services " " 2.0.50727.42 " )]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute(
" code " )]
    [System.Web.Services.WebServiceBindingAttribute(Name
= " ICalculate " , Namespace = " http://dev.robinzhong.com/ICalculate/ " )]
    
public  partial  class CalculateProxy : System.Web.Services.Protocols.SoapHttpClientProtocol  {
        
        
private System.Threading.SendOrPostCallback AddOperationCompleted;
        
        
private System.Threading.SendOrPostCallback SubOperationCompleted;
        
        
private bool useDefaultCredentialsSetExplicitly;
        

修改此类,让其从IICalculate继承.然后修改构造函数,让其通过构造函数得到Web Service的Url.如下:

[System.CodeDom.Compiler.GeneratedCodeAttribute( " System.Web.Services " " 2.0.50727.42 " )]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute(
" code " )]
    [System.Web.Services.WebServiceBindingAttribute(Name
= " ICalculate " , Namespace = " http://dev.robinzhong.com/ICalculate/ " )]
    
public  partial  class CalculateProxy : System.Web.Services.Protocols.SoapHttpClientProtocol,IICalculate  {
        
        
private System.Threading.SendOrPostCallback AddOperationCompleted;
        
        
private System.Threading.SendOrPostCallback SubOperationCompleted;
        
        
private bool useDefaultCredentialsSetExplicitly;
        
        
/// <remarks/>
        public
CalculateProxy (string url) {
            
this.Url = url;
            
if ((this.IsLocalFileSystemWebService(this.Url) == true)) {
                
this.UseDefaultCredentials = true;
                
this.useDefaultCredentialsSetExplicitly = false;
            }

            
else {
                
this.useDefaultCredentialsSetExplicitly = true;
            }

        }


6. 好了,可以开始测试我们的代码了:

IICalculate calculate;

calculate 
=   new  CalculateProxy(  " http://localhost:2935/SimpleCalculate.asmx " );
Console.WriteLine( 
" calculate.Add( 10, 345 ) =  "   +  calculate.Add(  10 345  ) );
Console.WriteLine( 
" calculate.Sub( 3455, 234 ) =  "   +  calculate.Sub(  3455 234  ) );

calculate 
=   new  CalculateProxy(  " http://localhost:2935/NewCalculate.asmx " );
Console.WriteLine( 
" calculate.Add( 10, 345 ) =  "   +  calculate.Add(  10 345  ) );
Console.WriteLine( 
" calculate.Sub( 3455, 234 ) =  "   +  calculate.Sub(  3455 234  ) );

这样就达到了Web Service Interface的目的了--我不管是那里的Web Service,反正只要实现了上面的接口,给我正确的url地址,我就可以调用...

其实,我们可以用更幽雅的方式实现: Contract First . Web Service不是RPC,它只传输数据,你只要定义发送方和接收方的消息格式就够了.
推荐大家看看 :
http://www.thinktecture.com/Resources/Software/WSContractFirst/default.html
http://msdn.microsoft.com/msdnmag/issues/05/05/ServiceStation/

SOA ? :)

 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值