zoukankan      html  css  js  c++  java
  • 基于Web Service的客户端框架搭建三:代理层(Proxy)

    前言

      代理层的主要工作是调用Web Service,将在FCL层序列化好的Json数据字符串Post到Web Service,然后获得Reponse,再从响应流中读取到调用结果Json字符串,在Dispatcher反序列化成数据对象,在UI层呈现出来。

    HttpHelper类(参考自:http://blog.csdn.net/eriloan/article/details/7000790)

      刚开始是直接在Proxy类中直接写的Post方法,后来看到这篇帖子,将Http相关的部分封装成了工具类HttpHelper。原帖中还包含了使用TCPSocket发送请求调用WebService的内容。

      1 namespace ProjectmsMGT_Proxy
      2 {
      3     public class HttpHelper
      4     {
      5         /// <summary>
      6         /// Http请求URL
      7         /// </summary>
      8         public string Url { set; get; }
      9 
     10         /// <summary>
     11         /// 请求参数Key(约定服务方法参数名同名)
     12         /// 在使用Post方式向服务器端发送请求的时候,请求数据中包含了参数部分,参数部分我们需要告诉WebService接口方法,实参要传给的接口方法行参名,由RequestParaKey指定
     13         /// 当然当接口方法有多个形参时,就不建议单独设计这样一个属性,直接在sendMsg中添加,此处只是为了突出RequestParaKey的重要性
     14         /// </summary>
     15         public string RequestParaKey { set; get; }
     16         
     17         /// <summary>
     18         /// 证书文件路径
     19         /// </summary>
     20         public string CertificateFilePath { set; get; }
     21 
     22         /// <summary>
     23         /// 证书文件口令
     24         /// </summary>
     25         public string CertificateFilePwd { set; get; }
     26 
     27         /// <summary>
     28         /// 构造函数,不使用证书
     29         /// </summary>
     30         /// <param name="url"></param>
     31         /// <param name="requestParaKey"></param>
     32         public HttpHelper(string url, string requestParaKey)
     33         {
     34             this.Url = url;
     35             this.RequestParaKey = requestParaKey;
     36         }
     37 
     38         /// <summary>
     39         /// 构造函数,使用证书
     40         /// </summary>
     41         /// <param name="url"></param>
     42         /// <param name="requestParaKey"></param>
     43         /// <param name="certFilePath"></param>
     44         /// <param name="certFilePwd"></param>
     45         public HttpHelper(string url, string requestParaKey, string certFilePath, string certFilePwd)
     46         {
     47             this.Url = url;
     48             this.RequestParaKey = requestParaKey;
     49             this.CertificateFilePath = certFilePath;
     50             this.CertificateFilePwd = certFilePwd;
     51         }
     52 
     53         /// <summary>
     54         /// 使用Get方式,发送Http请求
     55         /// </summary>
     56         /// <param name="methodName">所请求的接口方法名</param>
     57         /// <param name="isLoadCert">是否加载证书</param>
     58         /// <returns>响应字符串</returns>
     59         public string CreateHttpGet(string methodName, bool isLoadCert)
     60         {
     61             HttpWebRequest request = CreateHttpRequest(methodName, @"GET", isLoadCert);
     62 
     63             return CreateHttpResponse(request);
     64         }
     65 
     66         /// <summary>
     67         /// 使用Post方式,发送Http请求
     68         /// </summary>
     69         /// <param name="methodName">所请求的接口方法名</param>
     70         /// <param name="sendMsg">请求参数(不包含RequestParaKey部分)</param>
     71         /// <param name="isLoadCert">是否加载证书</param>
     72         /// <returns>响应字符串</returns>
     73         public string CreateHttpPost(string methodName, string sendMsg, bool isLoadCert)
     74         {
     75             //创建Http请求
     76             HttpWebRequest request = CreateHttpRequest(methodName, @"POST", isLoadCert);
     77             if (null != sendMsg && !"".Equals(sendMsg))
     78             {
     79                 //添加请求参数
     80                 AddHttpRequestParams(request, sendMsg);
     81             }
     82 
     83             //获得响应
     84             return CreateHttpResponse(request);
     85         }
     86 
     87         /// <summary>
     88         /// 将请求参数写入请求流
     89         /// </summary>
     90         /// <param name="request"></param>
     91         /// <param name="sendMsg"></param>
     92         private void AddHttpRequestParams(HttpWebRequest request, string sendMsg)
     93         {
     94             //将请求参数进行URL编码
     95             string paraUrlCoded = System.Web.HttpUtility.UrlEncode(RequestParaKey) + "=" +
     96                 System.Web.HttpUtility.UrlEncode(sendMsg);
     97 
     98             byte[] data = Encoding.UTF8.GetBytes(paraUrlCoded);
     99             request.ContentLength = data.Length;
    100             Stream requestStream = null;
    101             using (requestStream = request.GetRequestStream())
    102             {
    103                 //将请求参数写入流
    104                 requestStream.Write(data, 0, data.Length);
    105             }
    106 
    107             requestStream.Close(); 
    108         }
    109 
    110         /// <summary>
    111         /// 创建HttpRequest
    112         /// </summary>
    113         /// <param name="methodName"></param>
    114         /// <param name="requestType">POST或者GET</param>
    115         /// <param name="isLoadCert"></param>
    116         /// <returns>HttpWebRequest对象</returns>
    117         private HttpWebRequest CreateHttpRequest(string methodName, string requestType, bool isLoadCert)
    118         {
    119             HttpWebRequest request = null;
    120             try
    121             {
    122                 string requestUriString = Url + "/" + methodName;
    123                 request = (HttpWebRequest)WebRequest.Create(requestUriString);
    124                 if (isLoadCert)
    125                 {
    126                     //创建证书
    127                     X509Certificate2 cert = CreateX509Certificate2();
    128                     //添加证书认证
    129                     request.ClientCertificates.Add(cert);
    130                 }
    131                 request.KeepAlive = true;
    132                 request.ContentType = "application/x-www-form-urlencoded";
    133                 request.Method = requestType;
    134             }
    135             catch (Exception)
    136             {
    137                 //Console.WriteLine("创建HttpRequest失败。原因:" + e.Message);
    138                 request = null;
    139             }
    140 
    141             return request;
    142         }
    143 
    144         /// <summary>
    145         /// 创建请求响应
    146         /// </summary>
    147         /// <param name="request"></param>
    148         /// <returns>响应字符串</returns>
    149         private string CreateHttpResponse(HttpWebRequest request)
    150         {
    151             String str;
    152             HttpWebResponse response = null;
    153             Stream responseStream = null;
    154             XmlTextReader responseReader = null;
    155             try
    156             {
    157                 using (response = (HttpWebResponse)request.GetResponse())
    158                 {
    159                     //获得响应流
    160                     responseStream = response.GetResponseStream();
    161                     responseReader = new XmlTextReader(responseStream);
    162                     responseReader.MoveToContent();
    163                     str = responseReader.ReadInnerXml();
    164                 }
    165             }
    166             catch (Exception e)
    167             {
    168                 str = "[{"Rescode":"0","Resmsg":"通信失败。原因:" + e.Message + ""}]";
    169             }
    170             finally
    171             {
    172                 if (null != response)
    173                 {
    174                     responseReader.Close();
    175                     responseStream.Close();
    176                     response.Close();
    177                 }
    178             }
    179 
    180             return str; 
    181         }
    182 
    183         /// <summary>
    184         /// 创建证书
    185         /// </summary>
    186         /// <returns>X509Certificate2对象</returns>
    187         private X509Certificate2 CreateX509Certificate2()
    188         {
    189             X509Certificate2 cert = null;
    190             try
    191             {
    192                 cert = new X509Certificate2(CertificateFilePath, CertificateFilePwd);
    193                 ServicePointManager.ServerCertificateValidationCallback = 
    194                     new RemoteCertificateValidationCallback(ServerCertificateValidationCallback);
    195             }
    196             catch (Exception)
    197             {
    198                 //Console.WriteLine("创建X509Certificate2失败。原因:" + e.Message);  
    199                 cert = null;
    200             }
    201             return cert;
    202         }
    203 
    204         /// <summary>
    205         /// Verifies the remote Secure Sockets Layer (SSL) certificate used for authentication
    206         /// </summary>
    207         /// <param name="obj">An object that contains state information for this validation</param>
    208         /// <param name="cer">The certificate used to authenticate the remote party</param>
    209         /// <param name="chain">The chain of certificate authorities associated with the remote certificate</param>
    210         /// <param name="error">One or more errors associated with the remote certificate</param>
    211         /// <returns>A Boolean value that determines whether the specified certificate is accepted for authentication</returns>
    212         private bool ServerCertificateValidationCallback(object obj, X509Certificate cer, X509Chain chain, System.Net.Security.SslPolicyErrors error)
    213         {
    214             return true;
    215         } 
    216     }
    217 }

      HttpHelper中把SSL证书的部分也包含进来,但是证书认证机制部分ServerCertificateValidationCallback还没设计,各位大神可以自行发挥。

    代理类Proxy

      有了HttpHelper之后,代理类的代码就比较明了了。

     1 namespace ProjectmsMGT_Proxy
     2 {
     3     public class ProjectmsProxy
     4     {
     5         private readonly string Url = "http://59.68.29.106:8087/IFT_Project.asmx";//通过配置文件获取Web Service地址
     6         private readonly string requestParaKey = "paramaters";//服务端所有接口函数统一的参数名
     7         private HttpHelper httpHelper;
     8 
     9         public ProjectmsProxy()
    10         {
    11             //初始化
    12             Initialize();
    13         }
    14 
    15         private void Initialize()
    16         {
    17             httpHelper = new HttpHelper(this.Url, this.requestParaKey);
    18         }
    19 
    20         /// <summary>
    21         /// 使用Get方式调用WebService,不带参数
    22         /// </summary>
    23         /// <param name="methodName"></param>
    24         /// <param name="parasJsonStr"></param>
    25         /// <param name="requestType"></param>
    26         /// <returns></returns>
    27         public string Excute(string methodName, string parasJsonStr, string requestType)
    28         {
    29             return httpHelper.CreateHttpGet(methodName, false);
    30         }
    31 
    32         /// <summary>
    33         /// 默认使用Post方式调用WebService,带参数
    34         /// </summary>
    35         /// <param name="methodName"></param>
    36         /// <param name="parasJsonStr"></param>
    37         /// <returns></returns>
    38         public string Excute(string methodName, string parasJsonStr)
    39         {
    40             return httpHelper.CreateHttpPost(methodName, parasJsonStr, false);
    41         }
    42 
    43         /// <summary>
    44         /// 默认使用Post方式调用WebService,不带参数
    45         /// </summary>
    46         /// <param name="methodName"></param>
    47         /// <returns></returns>
    48         public string Excute(string methodName)
    49         {
    50             return httpHelper.CreateHttpPost(methodName, null, false);
    51         }
    52     }
    53 }

      Proxy中重载了Excute方法,三个参数的表示使用Get方式调用WebService(因为不建议在Get方式下传参给Web Service),两个参数和一个参数的Excute默认是使用Post方式带参数和不带参数的情况。

    总结

      将方法名作为参数Post到Web Service可以减少很多重复代码,不需要对服务端的每个接口函数做写一个代理函数,这是使用Post方式比使用添加Web服务引用方式更加灵活。

  • 相关阅读:
    百万级数据迁移方案测评小记
    EFCore-一对一配置外键小记2
    mpvue实战-手势滑动导航栏
    React-Native WebView使用本地js,css渲染html
    Dubbo测试环境服务调用隔离这么玩对么
    Kitty中的动态线程池支持Nacos,Apollo多配置中心了
    嘘!异步事件这样用真的好么?
    一时技痒,撸了个动态线程池,源码放Github了
    熬夜之作:一文带你了解Cat分布式监控
    这个Maven依赖的问题,你敢说你没遇到过
  • 原文地址:https://www.cnblogs.com/caiwenz/p/3913461.html
Copyright © 2011-2022 走看看