还是那几句话:
学无止境,精益求精
十年河东,十年河西,莫欺少年穷
学历代表你的过去,能力代表你的现在,学习代表你的将来
废话不多说,直接进入正题:
今天公司总部要求各个分公司把短信接口对接上,所谓的短信接口其实就是GET或者Post请求,接到这个任务感觉好Easy。
但是真正写起来,你会发现各种各样的问题,比如请求报401错误,报400错误,报..等等各种意想不到的错误!总之,在这个过程中尝试了三个方法:
第一个方法如下(由于第一个方法封装的比较多,在此仅仅截图),如下:
小矩形内得POST方法,结果发现报400错误。
紧接着我又尝试了第二种方法(这种方法比较简单,一般的POST请求都可以完成)
第二种方法如下(2014年微信公众号开发中,好多请求我都用的这个方法):
public static string GetPage(string posturl, string postData)
{
//WX_SendNews news = new WX_SendNews();
//posturl: news.Posturl;
//postData:news.PostData;
System.IO.Stream outstream = null;
Stream instream = null;
StreamReader sr = null;
HttpWebResponse response = null;
HttpWebRequest request = null;
Encoding encoding = Encoding.UTF8;
byte[] data = encoding.GetBytes(postData);
// 准备请求...
try
{
// 设置参数
request = WebRequest.Create(posturl) as HttpWebRequest;
CookieContainer cookieContainer = new CookieContainer();
request.CookieContainer = cookieContainer;
request.AllowAutoRedirect = true;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
outstream = request.GetRequestStream();
outstream.Write(data, , data.Length);
outstream.Close();
//发送请求并获取相应回应数据
response = request.GetResponse() as HttpWebResponse;
//直到request.GetResponse()程序才开始向目标网页发送Post请求
instream = response.GetResponseStream();
sr = new StreamReader(instream, encoding);
//返回结果网页(html)代码
string content = sr.ReadToEnd();
string err = string.Empty; return content;
}
catch (Exception ex)
{
string err = ex.Message;
return string.Empty;
}
}
结果这个方法报401错误。
无奈,又在Git Hub上找了个方法,如下:
/*
* Created by SharpDevelop.
* User: RedXu
* Date: 2015-04-16
* Time: 13:58
*
*/
using System;
using System.Net;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates; namespace RedXuCSharpClass
{
/// <summary>
/// Http操作类.
/// </summary>
public class HttpHelper
{
private const int ConnectionLimit = ;
//编码
private Encoding _encoding = Encoding.Default;
//浏览器类型
private string[] _useragents = new string[]{
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)",
"Mozilla/5.0 (Windows NT 6.1; rv:36.0) Gecko/20100101 Firefox/36.0",
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20130401 Firefox/31.0"
}; private String _useragent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36";
//接受类型
private String _accept = "text/html, application/xhtml+xml, application/xml, */*";
//超时时间
private int _timeout = * ;
//类型
private string _contenttype = "application/x-www-form-urlencoded";
//cookies
private String _cookies = "";
//cookies
private CookieCollection _cookiecollection;
//custom heads
private Dictionary<string, string> _headers = new Dictionary<string, string>(); public HttpHelper()
{
_headers.Clear();
//随机一个useragent
_useragent = _useragents[new Random().Next(, _useragents.Length)];
//解决性能问题?
ServicePointManager.DefaultConnectionLimit = ConnectionLimit;
} public void InitCookie()
{
_cookies = "";
_cookiecollection = null;
_headers.Clear();
} /// <summary>
/// 设置当前编码
/// </summary>
/// <param name="en"></param>
public void SetEncoding(Encoding en)
{
_encoding = en;
} /// <summary>
/// 设置UserAgent
/// </summary>
/// <param name="ua"></param>
public void SetUserAgent(String ua)
{
_useragent = ua;
} public void RandUserAgent()
{
_useragent = _useragents[new Random().Next(, _useragents.Length)];
} public void SetCookiesString(string c)
{
_cookies = c;
} /// <summary>
/// 设置超时时间
/// </summary>
/// <param name="sec"></param>
public void SetTimeOut(int msec)
{
_timeout = msec;
} public void SetContentType(String type)
{
_contenttype = type;
} public void SetAccept(String accept)
{
_accept = accept;
} /// <summary>
/// 添加自定义头
/// </summary>
/// <param name="key"></param>
/// <param name="ctx"></param>
public void AddHeader(String key, String ctx)
{
//_headers.Add(key,ctx);
_headers[key] = ctx;
} /// <summary>
/// 清空自定义头
/// </summary>
public void ClearHeader()
{
_headers.Clear();
} /// <summary>
/// 获取HTTP返回的内容
/// </summary>
/// <param name="response"></param>
/// <returns></returns>
private String GetStringFromResponse(HttpWebResponse response)
{
String html = "";
try
{
Stream stream = response.GetResponseStream();
StreamReader sr = new StreamReader(stream, _encoding);
html = sr.ReadToEnd(); sr.Close();
stream.Close();
}
catch (Exception e)
{
Trace.WriteLine("GetStringFromResponse Error: " + e.Message);
} return html;
} /// <summary>
/// 检测证书
/// </summary>
/// <param name="sender"></param>
/// <param name="certificate"></param>
/// <param name="chain"></param>
/// <param name="errors"></param>
/// <returns></returns>
private bool CheckCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{
return true;
} /// <summary>
/// 发送GET请求
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public String HttpGet(String url)
{
return HttpGet(url, url);
} /// <summary>
/// 发送GET请求
/// </summary>
/// <param name="url"></param>
/// <param name="refer"></param>
/// <returns></returns>
public String HttpGet(String url, String refer)
{
String html;
try
{
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckCertificate);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.UserAgent = _useragent;
request.Timeout = _timeout;
request.ContentType = _contenttype;
request.Accept = _accept;
request.Method = "GET";
request.Referer = refer;
request.KeepAlive = true;
request.AllowAutoRedirect = true;
request.UnsafeAuthenticatedConnectionSharing = true;
request.CookieContainer = new CookieContainer();
//据说能提高性能
request.Proxy = null;
if (_cookiecollection != null)
{
foreach (Cookie c in _cookiecollection)
{
c.Domain = request.Host;
} request.CookieContainer.Add(_cookiecollection);
} foreach (KeyValuePair<String, String> hd in _headers)
{
request.Headers[hd.Key] = hd.Value;
} HttpWebResponse response = (HttpWebResponse)request.GetResponse();
html = GetStringFromResponse(response);
if (request.CookieContainer != null)
{
response.Cookies = request.CookieContainer.GetCookies(request.RequestUri);
} if (response.Cookies != null)
{
_cookiecollection = response.Cookies;
}
if (response.Headers["Set-Cookie"] != null)
{
string tmpcookie = response.Headers["Set-Cookie"];
_cookiecollection.Add(ConvertCookieString(tmpcookie));
} response.Close();
return html;
}
catch (Exception e)
{
Trace.WriteLine("HttpGet Error: " + e.Message);
return String.Empty;
}
} /// <summary>
/// 获取MINE文件
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public Byte[] HttpGetMine(String url)
{
Byte[] mine = null;
try
{
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckCertificate);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.UserAgent = _useragent;
request.Timeout = _timeout;
request.ContentType = _contenttype;
request.Accept = _accept;
request.Method = "GET";
request.Referer = url;
request.KeepAlive = true;
request.AllowAutoRedirect = true;
request.UnsafeAuthenticatedConnectionSharing = true;
request.CookieContainer = new CookieContainer();
//据说能提高性能
request.Proxy = null;
if (_cookiecollection != null)
{
foreach (Cookie c in _cookiecollection)
c.Domain = request.Host;
request.CookieContainer.Add(_cookiecollection);
} foreach (KeyValuePair<String, String> hd in _headers)
{
request.Headers[hd.Key] = hd.Value;
} HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream stream = response.GetResponseStream();
MemoryStream ms = new MemoryStream(); byte[] b = new byte[];
while (true)
{
int s = stream.Read(b, , b.Length);
ms.Write(b, , s);
if (s == || s < b.Length)
{
break;
}
}
mine = ms.ToArray();
ms.Close(); if (request.CookieContainer != null)
{
response.Cookies = request.CookieContainer.GetCookies(request.RequestUri);
} if (response.Cookies != null)
{
_cookiecollection = response.Cookies;
}
if (response.Headers["Set-Cookie"] != null)
{
_cookies = response.Headers["Set-Cookie"];
} stream.Close();
stream.Dispose();
response.Close();
return mine;
}
catch (Exception e)
{
Trace.WriteLine("HttpGetMine Error: " + e.Message);
return null;
}
} /// <summary>
/// 发送POST请求
/// </summary>
/// <param name="url"></param>
/// <param name="data"></param>
/// <returns></returns>
public String HttpPost(String url, String data)
{
return HttpPost(url, data, url);
} /// <summary>
/// 发送POST请求
/// </summary>
/// <param name="url"></param>
/// <param name="data"></param>
/// <param name="refer"></param>
/// <returns></returns>
public String HttpPost(String url, String data, String refer)
{
String html;
try
{
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckCertificate);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.UserAgent = _useragent;
request.Timeout = _timeout;
request.Referer = refer;
request.ContentType = _contenttype;
request.Accept = _accept;
request.Method = "POST";
request.KeepAlive = true;
request.AllowAutoRedirect = true;
request.CookieContainer = new CookieContainer();
//据说能提高性能
request.Proxy = null; if (_cookiecollection != null)
{
foreach (Cookie c in _cookiecollection)
{
c.Domain = request.Host;
if (c.Domain.IndexOf(':') > )
c.Domain = c.Domain.Remove(c.Domain.IndexOf(':'));
}
request.CookieContainer.Add(_cookiecollection);
} foreach (KeyValuePair<String, String> hd in _headers)
{
request.Headers[hd.Key] = hd.Value;
}
byte[] buffer = _encoding.GetBytes(data.Trim());
request.ContentLength = buffer.Length;
request.GetRequestStream().Write(buffer, , buffer.Length);
request.GetRequestStream().Close(); HttpWebResponse response = (HttpWebResponse)request.GetResponse();
html = GetStringFromResponse(response);
if (request.CookieContainer != null)
{
response.Cookies = request.CookieContainer.GetCookies(request.RequestUri);
}
if (response.Cookies != null)
{
_cookiecollection = response.Cookies;
}
if (response.Headers["Set-Cookie"] != null)
{
string tmpcookie = response.Headers["Set-Cookie"];
_cookiecollection.Add(ConvertCookieString(tmpcookie));
} response.Close();
return html;
}
catch (Exception e)
{
Trace.WriteLine("HttpPost Error: " + e.Message);
return String.Empty;
}
} public string UrlEncode(string str)
{
StringBuilder sb = new StringBuilder();
byte[] byStr = _encoding.GetBytes(str);
for (int i = ; i < byStr.Length; i++)
{
sb.Append(@"%" + Convert.ToString(byStr[i], ));
} return (sb.ToString());
} /// <summary>
/// 转换cookie字符串到CookieCollection
/// </summary>
/// <param name="ck"></param>
/// <returns></returns>
private CookieCollection ConvertCookieString(string ck)
{
CookieCollection cc = new CookieCollection();
string[] cookiesarray = ck.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
for (int i = ; i < cookiesarray.Length; i++)
{
string[] cookiesarray_2 = cookiesarray[i].Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
for (int j = ; j < cookiesarray_2.Length; j++)
{
string[] cookiesarray_3 = cookiesarray_2[j].Trim().Split("=".ToCharArray());
if (cookiesarray_3.Length == )
{
string cname = cookiesarray_3[].Trim();
string cvalue = cookiesarray_3[].Trim();
if (cname.ToLower() != "domain" && cname.ToLower() != "path" && cname.ToLower() != "expires")
{
Cookie c = new Cookie(cname, cvalue);
cc.Add(c);
}
}
}
} return cc;
} public void DebugCookies()
{
Trace.WriteLine("**********************BEGIN COOKIES*************************");
foreach (Cookie c in _cookiecollection)
{
Trace.WriteLine(c.Name + "=" + c.Value);
Trace.WriteLine("Path=" + c.Path);
Trace.WriteLine("Domain=" + c.Domain);
}
Trace.WriteLine("**********************END COOKIES*************************");
} }
}
结果又是没能跳出错误的怪圈,依然是401错误。
于是,我不得不温习下 C# HttpClient 的相关方法
最后,还好,在公司的项目中有这种用到 HttpClient 的方法,于是抱着尝试的心里,作了测试,结果成功了!
本人写这篇博客也是做一个记录,方便自己以后用,也方便大家遇到 WebApi请求失败时,可以尝试上述的几种方法。
代码如下:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks; namespace KMHC.Infrastructure
{
public class SmsSendHelper
{
public string _appKey = "";
public string _category = "";
public string _templateNo = "";
public string _templateid = "";
public SmsSendHelper() { }
public async Task<SmsSendResult> Send(string phone, string sendContent)
{
var Model = BuildData(phone, sendContent);
SmsSendResult Result = new SmsSendResult();
var hh = new HttpClient() { BaseAddress = new Uri(SmsUri.SmsSendUri), Timeout = TimeSpan.FromMinutes() };
//Model 需要序列化的对象
var res = await hh.PostAsJsonAsync("", Model);
if (res.StatusCode == HttpStatusCode.OK)
{
var response = res.Content.ReadAsAsync<SmsSendResult>().Result;
return response;
}
return null;
} /// <summary>
/// 构建请求实体
/// </summary>
/// <param name="_phone"></param>
/// <param name="_sendContent"></param>
/// <returns></returns>
private object BuildData(string _phone, string _sendContent)
{
var para = new
{
appKey = _appKey,
category = _category,
templateNo = _templateNo,
templateid = _templateid,
phone = _phone,
sendContent = _sendContent
};
return para;
}
}
}
[Route("test"), HttpGet, AllowAnonymous]
public async Task<IHttpActionResult> test()
{
SmsSendHelper Func = new SmsSendHelper();
var data =await Func.Send("181XXXX0152","你好!短信测试。");
return Ok(data);
}
需要引用如下命名空间:
总之,很简单,也很好用。
@陈卧龙的博客