WebService学习总结

1.1    基础概念

       Web Service是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的独立的通讯技术。通过SOAPWeb上提供的服务,使用WSDL文件进行说明,并通过UDDI进行注册。

XML(Extensible Markup Language)扩展型可标记语言。面向短期的临时数据处理、面向万维网络,是Soap的基础。

Soap(Simple Object Access Protocol)简单对象存取协议。是XML Web Service 的通信协议。当用户通过UDDI找到你的WSDL描述文档后,他通过可以SOAP调用你建立的Web服务中的一个或多个操作。SOAPXML文档形式的调用方法的规范,它可以支持不同的底层接口,像HTTP(S)或者SMTP

WSDL(Web Services Description Language) WSDL 文件是一个 XML 文档,用于说明一组 SOAP 消息以及如何交换这些消息。大多数情况下由软件自动生成和使用。

UDDI (Universal Description Discovery and Integration) 是一种根据描述文档来引导系统查找相应服务的机制。UDDI利用SOAP消息机制(标准的XML/HTTP)来发布,编辑,浏览以及查找注册信息。它采用XML格式来封装各种不同类型的数据,并且发送到注册中心或者由注册中心来返回需要的数据。

    

1.2  Webservice基础实例

 

代码
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Web;
using  System.Web.Services;

namespace  AspNetWebServiceClient
{
    
///   <summary>
    
///  Service1 的摘要说明
    
///   </summary>
    [WebService(Namespace  =   " http://tempuri.org/ " )]
    [WebServiceBinding(ConformsTo 
=  WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(
false )]
    
//  若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。
    
//  [System.Web.Script.Services.ScriptService]
     public   class  Service1 : System.Web.Services.WebService
    {

        [WebMethod]
        
public   string  HelloWorld()
        {
            
return   " Hello World " ;
        }

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

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

    }
}

 

直接运行看看效果,

WebService学习总结_第1张图片

 

1.3    WebservicewebMethod的各种特性:

 

属性

功能

示例

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参与事务处理。其值可以是NotSupportedSupportedRequiredRequiresNew

[WebMethod(TransactionOption=System.EnterpriseServices.TransactionOption.Sup

关于Session的特性见下面,其他的特性的代码实例就不贴了

服务端代码:

代码
        [WebMethod(EnableSession  =   true )]
        
public   void   Login( string  userName)
        {
            
if  (userName.Length  >   0 )
            {
                Session[
" Name " =  userName;
            }
        }

        [WebMethod(EnableSession 
=   true )]
        
public   string  TestSession()
        {
            
string  userName  =  Session[ " Name " ].ToString();
            
return  userName;
        }

 

客户端代码:

 

代码
            localhost.Service1 proxy =   new  SimpleWebService.localhost.Service1();
            proxy.CookieContainer 
=   new  System.Net.CookieContainer();
            proxy.Login(
" 123 " );
            Label1.Text 
=  proxy.TestSession().ToString();

 

 

1.4 WebService的异步开发模式

 

当用到WebService时,由于服务器处理速度、网络传输速度等各种原因会使一个WebService从请求开始到获得响应结果之间等待一段时间,这时候线程会处于阻塞状态,程序会等待请求结果导致客户端无法进行其他的动作或处理。这时候就需要异步的使用WebService 

 

代码
         public   void  TestAsyncWebService()
        {
             localhost3.AsyncWebService service 
=   new  localhost3.AsyncWebService();
             service.HelloWorldCompleted
+= new  WebClientTest.localhost3.HelloWorldCompletedEventHandler(service_HelloWorldCompleted);
             service.HelloWorldAsync(
" China " );
        }

        
void  service_HelloWorldCompleted( object  sender, WebClientTest.localhost3.HelloWorldCompletedEventArgs e)
        {
            
if  (e.Result  !=   null   &&  e.Result.Length  >   0 )
            {
                
string  result =  e.Result;
                Label3.Text 
=  result;
            }
            
if  (e.Error  !=   null )
            {
                Console.WriteLine(e.Error.Message);
            }   

        }

 

 

 

1.5    webService的验证方式及安全性

1.5.1   使用SOAP头来验证

服务端代码

代码
  public   class  SOAPWebService : System.Web.Services.WebService
    {

        [WebMethod]
        
public   string  HelloWorld()
        {
            
return   " Hello World " ;
        }

        
public  MySoapHeader header;
        [SoapHeader(
" header " , Direction  =  SoapHeaderDirection.In)]
        [WebMethod]
        
public   string  CheckHeader()
        {
            
if  (header  ==   null )
            {
                
throw   new  SoapHeaderException( " 认证失败 " , SoapException.ClientFaultCode);
            }
            
else
            {
                
if  (header.Name  !=   " admin "   ||  header.PassWord  !=   " admin " )
                {
                    
throw   new  SoapHeaderException( " 认证失败 " , SoapException.ClientFaultCode);
                }
            }
            
// 业务逻辑.
             return   " Something done " ;
        }

    }

    
public   class  MySoapHeader : SoapHeader
    {
        
string  _name;
        
string  _passWord;

        
public   string  Name
        {
            
get  {  return  _name; }
            
set  { _name  =  value; }
        }
        
public   string  PassWord
        {
            
get  {  return  _passWord; }
            
set  { _passWord  =  value; }
        }
    }

 

客户端代码:

 

代码
         public   void  TestSoapHeader()
        {
            MySoapHeader h 
=   new  MySoapHeader();
            h.Name 
=   " cqs " ;
            h.PassWord 
=   " 123 " ;
            localhost1.SOAPWebService service 
=   new  SOAPWebService();
            service.MySoapHeaderValue 
=  h;
            
try
            {
                
string  retval  =  service.CheckHeader();
                Label1.Text
= " Return: "   +  retval;
            }
            
catch  (SoapHeaderException soapEx)
            {
                Label2.Text
= " Soap Header Exception: "   +  soapEx.Message;
            }
            
catch  (Exception ex)
            {
                Label3.Text
= " Exception: "   +  ex.Message;
            }

        }

 

 

1.6 Webservice 的动态代理

在程序中需要调用WebService时,都是通过添加Web引用,让VS.NET环境来为我们生成服务代理,然后调用对应的Web服务。这样是使工作简单了,但是却和提供Web服务的URL、方法名、参数绑定在一起了,这是VS.NET自动为我们生成Web服务代理的限制。如果发布Web服务的URL改变了,则我们需要重新让VS.NET生成代理,并重新编译。动态调用WebService就能解决上述难题,比如我们可以Web服务的URL保存在配置文件中,这样,当服务URL改变时,只需要修改配置文件就可以了。具体的代码参见网上常见的动态代理类:

 

代码
         ///   <summary>
        
///  
        
///   </summary>
         public   void  TestDynamicWebService()
        {
            
try
            {
                
string  url  =   " http://localhost:4640/DynamicWebService.asmx " ;
                
string [] args  =   new   string [ 1 ];
                args[
0 =   " China " ;
                
object  result  =  DynamicWebServiceHelper.InvokeWebService(url,  " HelloWorld " , args);
                
this .Label1.Text  =  result.ToString();
            }
            
catch  (Exception ex)
            {
                Label3.Text 
=   " Exception: "   +  ex.Message;
            }

        }

 

上述的参数具体可以利用配置文件的方式获取,更增加灵活性,但是通过动态代理的方式将会使性能有所降低。

 

1.7   扩展SOAP

 

代码
     public   class  SoapExtensionWS : System.Web.Services.WebService
    {
        
public  MySoapHeader header;

        [WebMethod]
        
public   string  HelloWorld()
        {
            
return   " Hello World " ;
        }

        [MyExtensionAttribute]
        [SoapHeader(
" header " , Direction  =  SoapHeaderDirection.In)]
        [WebMethod]
        
public   string  CheckHeader()
        {
            
// 业务逻辑.
             return   " Something done " ;
        }

    }

    [AttributeUsage(AttributeTargets.Method)]
    
public   class  MyExtensionAttribute : SoapExtensionAttribute
    {
        
int  _priority  =   1 ;

        
public   override   int  Priority
        {
            
get  {  return  _priority; }
            
set  { _priority  =  value; }
        }

        
public   override  Type ExtensionType
        {
            
get  {  return   typeof (MyExtension); }
        }
    }

    
///   <summary>
    
///  
    
///   </summary>
     public   class  MyExtension : SoapExtension
    {
        
///   <summary>
        
///  
        
///   </summary>
        
///   <param name="message"></param>
         public   override   void  ProcessMessage(SoapMessage message)
        {
            
if  (message.Stage  ==  SoapMessageStage.AfterDeserialize) // 反序列化之后处理
            {
                
bool  check  =   false ;
                
foreach  (SoapHeader header  in  message.Headers)
                {
                    
if  (header  is  MySoapHeader)
                    {
                        MySoapHeader myHeader 
=  (MySoapHeader)header;

                        LogEntry log2 
=   new  LogEntry();
                        log2.Message 
=  myHeader.Name  +  myHeader.PassWord;
                        log2.Categories.Add(Category.ExceptionCategory);
                        log2.Priority 
=  Priority.Highest;
                        Logger.Write(log2);

                        
if  (myHeader.Name  ==   " admin "   ||  myHeader.PassWord  ==   " admin " )
                        {
                            check 
=   true ;
                            
break ;
                        }
                    }
                }
                
if  ( ! check)
                    
throw   new  SoapHeaderException( " 认证失败 " , SoapException.ClientFaultCode);
            }
        }

        
///   <summary>
        
///  
        
///   </summary>
        
///   <param name="type"></param>
        
///   <returns></returns>
         public   override  Object GetInitializer(Type type)
        {
            
return  GetType();
        }

        
///   <summary>
        
///  
        
///   </summary>
        
///   <param name="info"></param>
        
///   <param name="attribute"></param>
        
///   <returns></returns>
         public   override  Object GetInitializer(LogicalMethodInfo info, SoapExtensionAttribute attribute)
        {
            
return   null ;
        }

        
///   <summary>
        
///  
        
///   </summary>
        
///   <param name="initializer"></param>
         public   override   void  Initialize(Object initializer)
        {
        }
    }

    
public   class  MySoapHeader : SoapHeader
    {
        
string  _name;
        
string  _passWord;

        
public   string  Name
        {
            
get  {  return  _name; }
            
set  { _name  =  value; }
        }
        
public   string  PassWord
        {
            
get  {  return  _passWord; }
            
set  { _passWord  =  value; }
        }
    }

 

通过扩展SOAP可以针对消息做日志

  1.8  Webservice的异常处理

   Webservice客户端使用一个WebMethod时,如果WebMethod内部出现异常,不管异常是系统级异常或者自定义的异常,均会被包装为SoapException类型的异常,返回给客户端。

 

服务端代码:

代码
     public   class  Service1 : System.Web.Services.WebService
    {

        [WebMethod]
        
public   string  HelloWorld()
        {
            
return   " Hello World " ;
        }

        
///   <summary>
        
///  根据ID读取人员信息
        
///   </summary>
        
///   <returns> 人员信息类 </returns>
        [WebMethod]
        
public   int  Division( int  x, int  y)
        {
            
try
            {
                
return   x  /  y;
            }
            
catch  (System.Exception ex)
            {
                
throw   new  ExceptionHelper().RaiseException(
                                        
" Division " ,
                                        ex.Message,
                                        
" 1000 " ,
                                        ex.Source,
                                        FaultCode.Server
                                    );
            }
        }

        [WebMethod]
        
public   void  TestException()
        {
            
throw   new  SoapException( " Invalid Operation. " , SoapException.ServerFaultCode);
        } 

    }

    
///   <summary>
    
///  异常类型
    
///   </summary>
     public   enum  FaultCode
    {
        Client 
=   0 ,
        Server 
=   1
    }

    
public   class  ExceptionHelper
    {
        
///   <summary>
        
///  封装异常为SoapException
        
///   </summary>
        
///   <param name="uri"> 引发异常的方法uri </param>
        
///   <param name="errorMessage"> 错误信息 </param>
        
///   <param name="errorNumber"> 错误号 </param>
        
///   <param name="errorSource"> 错误源 </param>
        
///   <param name="code"> 异常类型 </param>
        
///   <returns> 封装后的SoapException </returns>
         public  SoapException RaiseException( string  uri,  string  errorMessage,  string  errorNumber,  string  errorSource, FaultCode code)
        {
            
// 初始化限定名
            XmlQualifiedName faultCodeLocation  =   null ;

            
// 异常类型代码转换
             switch  (code)
            {
                
case  FaultCode.Client:
                    faultCodeLocation 
=  SoapException.ClientFaultCode;
                    
break ;
                
case  FaultCode.Server:
                    faultCodeLocation 
=  SoapException.ServerFaultCode;
                    
break ;
            }

            
// 构建异常信息结构体
             string  strXmlOut  =   @" <detail> "
                             
+   " <Error> "
                             
+   " <ErrorNumber> "   +  errorNumber  +   " </ErrorNumber> "
                             
+   " <ErrorMessage> "   +  errorMessage  +   " </ErrorMessage> "
                             
+   " <ErrorSource> "   +  errorSource  +   " </ErrorSource> "
                             
+   " </Error> "
                             
+   " </detail> " ;

            
// 装载为Xml文档
            XmlDocument xmlDoc  =   new  XmlDocument();
            xmlDoc.LoadXml(strXmlOut);

            
// 实例化SoapException
            SoapException soapEx  =   new  SoapException(errorMessage, faultCodeLocation, uri, xmlDoc.DocumentElement);

            
// 返回SoapException
             return  soapEx;
        }

 

 

 

 

你可能感兴趣的:(webservice)