基于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服务引用方式更加灵活。

posted @ 2014-08-15 09:17  取啥名字  阅读(3153)  评论(3编辑  收藏  举报