1) 方案一,  使用Web Service  基础功能没问题, 只是在连接https (ssh) 网站时, 需要针对https进行开发 (即http 和https 生成两套接口, 不太容易统一 ).   后来改为使用web页面交互(实质是.ashx) 结果也遇到了不少问题.

 
2) 方案二, 使用 HttpWebRequest .    HttpWebRequest 这东西get数据很容易, POST却很麻烦, 最终代码如下:
 
  1. public class WebApiClient
  2. {
  3. public string Url { get; set; }
  4. private CookieContainer Cookies = new CookieContainer();
  5.  
  6. public static string Get( string url )
  7. {
  8. //this code can fix https after .net 4.6
  9. if (url.StartsWith("https", StringComparison.CurrentCultureIgnoreCase))
  10. {
  11. System.Net.ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
  12. }
  13. System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)WebRequest.Create(url);
  14. request.Method = "GET";
  15. request.ContentType = "application/x-www-form-urlencoded";
  16.  
  17. System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
  18. System.IO.Stream s = response.GetResponseStream();
  19. using (StreamReader reader = new StreamReader(s))
  20. {
  21. string strValue = reader.ReadToEnd();
  22. return strValue;
  23. }
  24. }
  25. private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
  26. {
  27. return true;
  28. }
  29. public Result<DataTable> CallWebApi(string action, string json )
  30. {
  31. return CallWebApi(action, json, null, null);
  32. }
  33. public Result<DataTable> CallWebApi(string action, string json, string fileName, byte[] fileData)
  34. {
  35. string responseContent;
  36. var memStream = new MemoryStream();
  37. var webRequest = (HttpWebRequest)WebRequest.Create(Url);
  38. var boundary = "---------------" + DateTime.Now.Ticks.ToString("x");
  39. var beginBoundary = Encoding.ASCII.GetBytes("--" + boundary + "\r\n");
  40. //var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
  41. var endBoundary = Encoding.ASCII.GetBytes("--" + boundary + "--\r\n");
  42. webRequest.Method = "POST";
  43. //webRequest.Timeout = timeOut;
  44. webRequest.ContentType = "multipart/form-data; boundary=" + boundary;
  45. if (!string.IsNullOrEmpty(fileName))
  46. {
  47. const string filePartHeader =
  48. "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" +
  49. "Content-Type: application/octet-stream\r\n\r\n";
  50. var header = string.Format(filePartHeader, "file1", fileName);
  51. var headerbytes = Encoding.UTF8.GetBytes(header);
  52. memStream.Write(beginBoundary, , beginBoundary.Length);
  53. memStream.Write(headerbytes, , headerbytes.Length);
  54. memStream.Write(fileData, , fileData.Length);
  55. }
  56.  
  57. var stringKeyHeader = "\r\n--" + boundary +
  58. "\r\nContent-Disposition: form-data; name=\"{0}\"" +
  59. "\r\n\r\n{1}\r\n";
  60. var bytes = Encoding.UTF8.GetBytes(string.Format(stringKeyHeader, "action", action));
  61. memStream.Write(bytes, , bytes.Length);
  62. bytes = Encoding.UTF8.GetBytes(string.Format(stringKeyHeader, "json", json));
  63. memStream.Write(bytes, , bytes.Length);
  64.  
  65. memStream.Write(endBoundary, , endBoundary.Length);
  66. webRequest.ContentLength = memStream.Length;
  67. var requestStream = webRequest.GetRequestStream();
  68. memStream.Position = ;
  69. var tempBuffer = new byte[memStream.Length];
  70. memStream.Read(tempBuffer, , tempBuffer.Length);
  71. memStream.Close();
  72. requestStream.Write(tempBuffer, , tempBuffer.Length);
  73. requestStream.Close();
  74. var httpWebResponse = (HttpWebResponse)webRequest.GetResponse();
  75. using (var httpStreamReader = new StreamReader(httpWebResponse.GetResponseStream(),
  76. Encoding.GetEncoding("utf-8")))
  77. {
  78. responseContent = httpStreamReader.ReadToEnd();
  79. }
  80. httpWebResponse.Close();
  81. webRequest.Abort();
  82. try
  83. {
  84. return JsonConvert.DeserializeObject<Result<DataTable>>(responseContent);
  85. }
  86. catch (Exception ex)
  87. {
  88. throw new ApplicationException("Parse server result error: " + responseContent, ex);
  89. }
  90. }
  91.  
  92. }
POST数据的麻烦, 封装一下可以忍了, 但是连接HTTPS的网站时, 有的网站可以, 有的网站会出错:System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   --- End of inner exception stack trace ---
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result)
   at System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.ConnectStream.WriteHeaders(Boolean async)
   --- End of inner exception stack trace ---
   at System.Net.HttpWebRequest.GetResponse()
 
如果是普通的桌面程序 , 在.net 4.6以上版本时, Create HttpWebRequest 对象前添加
  1. if(url.StartsWith("https",StringComparison.CurrentCultureIgnoreCase))
  2. {
  3. System.Net.ServicePointManager.ServerCertificateValidationCallback=newRemoteCertificateValidationCallback(CheckValidationResult);
  4. }
  1. privatestatic bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain,SslPolicyErrors errors)
  2. {
  3. returntrue;
  4. }
 
有的web服务器要求较新的HTTPS的安装协议, 这种情况下.net4.0以下的版本不支持, 因此要升级到.net4.6以上, 并且在创建HttpWebRequest对象前加入如下设置代码:
  1. ServicePointManager.SecurityProtocol=SecurityProtocolType.Tls|SecurityProtocolType.Tls11|SecurityProtocolType.Tls12|SecurityProtocolType.Ssl3;
这样就可以最大程度的兼容各种安全协议了. 有的时候发现我们的程序挑.net framework的版本, 大都是由这个原因引起的.
解决了HttpWebRequest连接HTTPS的问题之后, 该方案成为了功能最强的方案(重要是能较好的支持文件的上传)
 
方案三 使用WebBrowser控件 .
 
初步试了一下, get https的页面没有问题, post 的略有麻烦, 网上查到的方法是截获post事件进行处理:

WebBrowser 其实是对 ActiveX 控件 SHDocVw 的封装,而这个SHDocVw的很多底层调用WebBrowser控件并没有提供实现,我们需要直接操作 SHDoceVw 控件来实现这些高级调用。操作方法如下:
1、在 windows/system32 目录下找到 shdocvw.dll 这个动态库,将其添加到引用中

2、在 Form1_Load 中添加如下语句

  1. SHDocVw.WebBrowser wb = (SHDocVw.WebBrowser)webBrowser1.ActiveXInstance;
    wb.BeforeNavigate2 += new DWebBrowserEvents2_BeforeNavigate2EventHandler(WebBrowser_BeforeNavigate2);

3、添加如下成员函数

  1. private void WebBrowser_BeforeNavigate2(object pDisp, ref object URL, ref object Flags,
    ref object TargetFrameName, ref object PostData, ref object Headers, ref bool Cancel)
    {
    string postDataText = System.Text.Encoding.ASCII.GetString(PostData as byte[]);
    }

完成上述3步后,你post 数据时, 就会响应 BeforeNavigate2 事件,postDataText 中就是你post的数据。你也可以修改PostData,对这些数据进行转换或加密。

感觉会比较麻烦, 其实还有一种方法,就是利用WebBrowser的DocumentText属性注入脚本(执行脚本), 然后利用Ajax的方式和web服务器进行交互. 之后利用JS和C#互操作来完成相应的功能.

互操作的C#类上需要加上这个设置:
  1. [System.Runtime.InteropServices.ComVisibleAttribute(true)]
并且运行此代码:
  1. webBrowser1.ObjectForScripting=this;
C#里调用JS方法:
  1. webBrowser1.Document.InvokeScript("jsFunction",newstring[]{‘ssss’});
 
JS里调用C#方法:
  1. window.external.CSharpFunction(‘呵呵’);
这个方法也有些麻烦的地方, 而且不支持文件的上传.

记Outlook插件与Web页面交互的各种坑 (含c# HttpWebRequest 连接https 的完美解决方法)的更多相关文章

  1. (基础篇)PHP与Web页面交互

    PHP与Web页面交互是实现PHP网站与用户交互的重要手段.在PHP中提供了两种与Web页面交互的方法,一种是通过Web表单提交数据,另一种是通过URL参数传递. 这里我们将详细讲解表单的相关知识,为 ...

  2. PHP与web 页面交互

    PHP与Web页面交互是实现PHP网站与用户交互的重要手段.在PHP中提供了两种与Web页面交互的方法,一种是通过Web表单提交数据,另一种是通过URL参数传递. 这里我们将详细讲解表单的相关知识,为 ...

  3. 5.PHP与Web页面交互

    PHP与Web页面交互 PHP中提供了两种与Web页面交互的方法,一种是通过Web表单提交数据,另一种是通过URL参数传递. 表单提交用户名字和密码: <form name "form ...

  4. Chrome插件触发web页面的事件

    Chrome插件中不能直接调用Web页面的元素js,原因是chrome插件的机制http://stackoverflow.com/questions/17819344/triggering-a-cli ...

  5. php与web页面交互(二)

    一.获取表单数据 1.1 使用POST()方法提交表单  ---POST()方法可以没有限制地传递数据到服务器,所提交的数据在后台传输,用户在浏览器端是看不到这一过程的,安全性高,适用于发送保密数据和 ...

  6. php与web页面交互

    一.web表单 web表单的功能是让浏览者和网站有一个互动的平台.web表单主要用来在网页中发送数据到服务器. 1.1 表单的创建 使用form标记,并在其中插入相关的表单元素,即可创建一个表单. & ...

  7. web页面动态加载UserControl,并调用用户控件中的方法来初始化控件

    1,HTML页 头部注册: <%@ Register Src="~/WorkLog/WorkLogNewV1/UserControl/CeShiBu.ascx" TagPre ...

  8. JAVA and JAVA WEB with TOMCAT and ECLIPSE 学习过程中遇到的字符乱码问题及解决方法汇总(随时补充)

    JAVA语言具有跨平台,unicode字符集编码的特点. 但是在开发过程中处理数据时涉及到的字符编码问题零零散散,尤其是处理中文字符时一不留神就可能出现一堆奇奇怪怪的符号,俗称乱码. 对于乱码,究其原 ...

  9. Firefox火狐Flash插件卡死问题完美解决方法(转载)

    http://www.ihacksoft.com/firefox-flash-protectedmode.html 其实这个问题以前就出现过,而最近该问题又出现在最新的 Windows 8.1 系统中 ...

随机推荐

  1. go语言调用cmd

    package main import ( "fmt" "os/exec" ) func main() { //删除C:\Users\Administrator ...

  2. [转]Linux Socket编程 Socket抓取网页源码

    “一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. ——有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览 ...

  3. fzu2181(点的双连通分量+求奇环)

    求出每个点双连通分量,如果在一个点双连通分量中有奇环,则这个分量每个点都在一个奇环中.  关键是要知道怎么求点双连通分量以及点双连通的性质. fzu2181 http://acm.fzu.edu.cn ...

  4. Sass mixin 使用css border属性画三角形

    To be finished. //triangle@mixin css-triangle ($direction: "down", $size: 20px, $color: #0 ...

  5. 【BZOJ2140】稳定婚姻 Tarjan

    [BZOJ2140]稳定婚姻 Description 我国的离婚率连续7年上升,今年的头两季,平均每天有近5000对夫妇离婚,大城市的离婚率上升最快,有研究婚姻问题的专家认为,是与简化离婚手续有关. ...

  6. 1878: [SDOI2009]HH的项链

    1878: [SDOI2009]HH的项链 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 4420  Solved: 2199[Submit][Statu ...

  7. DropdownList异步刷新GridView数据

    前台代码: <div style=" clear:both; width:800px; text-align:center; margin-left:auto; margin-righ ...

  8. SpringBoot整合Dubbo报错: java.lang.ClassCastException

    com.alibaba.dubbo.rpc.RpcException: Failed to invoke remote proxy method queryGoodsLimitPage to regi ...

  9. iOS反射:把对象直接转化成NSDictionary

    在IOS的网络编程中,通常我们需要将一些实体数据保存到NSDictionary,在获得NSDictionary后即可直接使用iOS 5后的NSJSONSerialization类型的dataWithJ ...

  10. python函数的学习笔记

    这篇文章是我关于学习python函数的一些总结 一.随着函数的引入,这里首先要说的就是全局变量和局部变量了. 什么是全局变量.什么是局部变量: 全局变量就是全局都能调用的变量,一般都在文件的开头,顶头 ...