zoukankan      html  css  js  c++  java
  • 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;
            }

        }
    }

    直接运行看看效果,

    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;
            }

     

     

     

     

  • 相关阅读:
    HDU_5372 树状数组 (2015多校第7场1004)
    《 字典树模板_递归 》
    《神、上帝以及老天爷》
    《Crazy tea party》
    UVA_ Overflow
    UVA_If We Were a Child Again
    UVA_Product
    UVA_Integer Inquiry
    你也可以屌到爆的这样敲代码当黑客!
    大数相加_原创
  • 原文地址:https://www.cnblogs.com/chengqscjh/p/1921220.html
Copyright © 2011-2022 走看看