本片篇分享简单介绍C#中的Http请求,前几天帮朋友的项目封装ApiHelper,我粗糙的结果就如下,想想我真的是差的太远了。还有一位架构师也在封装这个Helper , 所以最后的结果当然是使用大牛的封装,这篇分享后,准备学习下他的封装,配置,错误处理机制等思想。不过这次也使我对C#网络编程了解的更多,算是一次学习经历吧。真心喜欢和老司机合作,下一阶段将会持续跟这位朋友学习项目底层的封装,和他谦虚的态度,有这样的机会也是幸运的。
你可以将其封装成自己的HttpHelper,经朋友建议,统一Http请求的入参和出参。在HttpClient方面也参考了dudu的关于httpclient预热的文章。C#中HttpClient使用注意:预热与长连接。
为了做到统一入参和出参,定义了Req<T>泛型类和Resp<T>泛型类。你可以根据自己的需要进行拓展。
public class Req<T>
{
/// <summary>
/// 传入数据
/// </summary>
public T Input { get; set; }
/// <summary>
/// 请求地址
/// </summary>
public string Url { get; set; }
}
public class Resp<T>
{
/// <summary>
/// 错误消息
/// </summary>
public string ErrorMsg { get; set; }
/// <summary>
/// 状态码
/// </summary>
public int StatusCode { get; set; }
/// <summary>
/// 返回数据
/// </summary>
public T RespData { get; set; }
}
虽然保持了httpClient对象复用,但需要注意的是,在设置了httpClient,并且发生了一次请求之后,不能再对其属性进行重新设置。这也正是我又定义了一个fileClient的理由。
#region HttpClient版本
private static readonly string _baseAddress = ConfigurationManager.AppSettings["api-server"];//配置BaseUrl eg.http://localhost:1234
private static readonly HttpClient _httpClient;
private static readonly HttpClient _fileClient; static ApiHelper()
{
#region 初始化和预热 httpClient
_httpClient = new HttpClient();
_httpClient.BaseAddress = new Uri(_baseAddress);
_httpClient.Timeout = TimeSpan.FromMilliseconds();
_httpClient.DefaultRequestHeaders.Add("Accept", "application/json");//application/xml 想Accept的数据格式 _httpClient.SendAsync(new HttpRequestMessage
{
Method = new HttpMethod("HEAD"),
RequestUri = new Uri(_baseAddress + "/api/test/HttpClientHot")
})
.Result.EnsureSuccessStatusCode();
#endregion #region 初始化和预热 fileClient _fileClient = new HttpClient();
_fileClient.BaseAddress = new Uri(_baseAddress + "/api/test/HttpClientHot");
_fileClient.MaxResponseContentBufferSize = ; #endregion
} /// <summary>
/// http Get请求
/// </summary>
/// <typeparam name="T">入参类型</typeparam>
/// <typeparam name="TResult">出参类型</typeparam>
/// <param name="req">入参对象</param>
/// <returns></returns>
public static async Task<Resp<TResult>> GetAsync<T, TResult>(Req<T> req)
{
try
{
var result =await _httpClient.GetAsync(req.Url).Result.Content.ReadAsStringAsync();
return new Resp<TResult>() { Data = JsonHelper.JsonDeserialize<TResult>(result) };
}
catch(Exception ex)
{ }
return new Resp<TResult>() { Data = JsonHelper.JsonDeserialize<TResult>("") }; } /// <summary>
/// http Post请求
/// </summary>
/// <typeparam name="T">入参类型</typeparam>
/// <typeparam name="TResult">出参类型</typeparam>
/// <param name="req">入参对象</param>
/// <returns></returns>
public static async Task<Resp<TResult>> PostAsJsonAsync<T, TResult>(Req<T> req)
{
var result = await _httpClient.PostAsJsonAsync(req.Url, req.Input).Result.Content.ReadAsStringAsync();
return new Resp<TResult>() { Data = JsonHelper.JsonDeserialize<TResult>(result) };
} /// <summary>
/// 上传文件
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="req"></param>
/// <param name="filePath"></param>
/// <returns></returns>
public static async Task<Resp<TResult>> SendFile<T, TResult>(Req<T> req, string filePath)//D:\\white.jpg
{
//_fileClient.DefaultRequestHeaders.Add("user-agent", "User-Agent Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; MALNJS; rv:11.0) like Gecko");//设置请求头
// 读文件流
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
HttpContent fileContent = new StreamContent(fs);//为文件流提供的HTTP容器
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");//设置媒体类型
MultipartFormDataContent mulContent = new MultipartFormDataContent("----");//创建用于可传递文件的容器
string fileName = filePath.Substring(filePath.LastIndexOf("/") + );
mulContent.Add(fileContent, "form", fileName);//第二个参数是表单名,第三个是文件名。
HttpResponseMessage response = await _fileClient.PostAsync(req.Url, mulContent);
response.EnsureSuccessStatusCode();
string result = await response.Content.ReadAsStringAsync();
return new Resp<TResult>() { Data = JsonHelper.JsonDeserialize<TResult>(result) };
} /// <summary>
/// 下载
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static async Task<Resp<byte[]>> HttpDownloadData<T>(Req<T> req)
{
var byteres = await _fileClient.GetByteArrayAsync(req.Url);
return new Resp<byte[]>() { Data = byteres };
} #endregion
}
另外分享下HttpWebRequest来实现的请求。HttpWebRequest需要你自行设置很多内容,当然这也证明其内容丰富。下面代码包含了post,get,以及上传。
/// <summary>
/// Post Http请求
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="postData">传输数据</param>
/// <param name="timeout">超时时间</param>
/// <param name="contentType">媒体格式</param>
/// <param name="encode">编码</param>
/// <returns>泛型集合</returns>
public static List<T> PostAndRespList<T>(string url, string postData, int timeout = , string contentType = "application/json;", string encode = "UTF-8")
{
if (!string.IsNullOrEmpty(url) && !string.IsNullOrEmpty(encode) && !string.IsNullOrEmpty(contentType) && postData != null)
{
// webRequest.Headers.Add("Authorization", "Bearer " + "SportApiAuthData");
HttpWebResponse webResponse = null;
Stream responseStream = null;
Stream requestStream = null;
StreamReader streamReader = null;
try
{
string respstr = GetStreamReader(url, responseStream, requestStream, streamReader, webResponse, timeout, encode, postData, contentType);
return JsonHelper.JsonDeserialize<List<T>>(respstr); }
catch (Exception ex)
{ }
finally
{
if (responseStream != null) responseStream.Dispose();
if (webResponse != null) webResponse.Dispose();
if (requestStream != null) requestStream.Dispose();
if (streamReader != null) streamReader.Dispose();
}
}
return null;
} /// <summary>
/// Post Http请求
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="postData">传输数据</param>
/// <param name="timeout">超时时间</param>
/// <param name="contentType">媒体格式</param>
/// <param name="encode">编码</param>
/// <returns>泛型集合</returns>
public static T PostAndRespSignle<T>(string url, int timeout = , string postData = "", string contentType = "application/json;", string encode = "UTF-8")
{
if (!string.IsNullOrEmpty(url) && !string.IsNullOrEmpty(encode) && !string.IsNullOrEmpty(contentType) && postData != null)
{
// webRequest.Headers.Add("Authorization", "Bearer " + "SportApiAuthData");
HttpWebResponse webResponse = null;
Stream responseStream = null;
Stream requestStream = null;
StreamReader streamReader = null;
try
{
string respstr = GetStreamReader(url, responseStream, requestStream, streamReader, webResponse, timeout, encode, postData, contentType);
return JsonHelper.JsonDeserialize<T>(respstr);
}
catch (Exception ex)
{ }
finally
{
if (responseStream != null) responseStream.Dispose();
if (webResponse != null) webResponse.Dispose();
if (requestStream != null) requestStream.Dispose();
if (streamReader != null) streamReader.Dispose();
}
}
return default(T);
} /// <summary>
/// Post Http请求
/// </summary>
/// <param name="url"></param>
/// <param name="postData"></param>
/// <param name="timeout"></param>
/// <param name="contentType"></param>
/// <param name="encode"></param>
/// <returns>响应流字符串</returns>
public static string PostAndRespStr(string url, int timeout = , string postData = "", string contentType = "application/json;", string encode = "UTF-8")
{
if (!string.IsNullOrEmpty(url) && !string.IsNullOrEmpty(encode) && !string.IsNullOrEmpty(contentType) && postData != null)
{
HttpWebResponse webResponse = null;
Stream responseStream = null;
Stream requestStream = null;
StreamReader streamReader = null;
try
{ return GetStreamReader(url, responseStream, requestStream, streamReader, webResponse, timeout, encode, postData, contentType);
}
catch (Exception ex)
{ }
finally
{
if (responseStream != null) responseStream.Dispose();
if (webResponse != null) webResponse.Dispose();
if (requestStream != null) requestStream.Dispose();
if (streamReader != null) streamReader.Dispose();
}
}
return null;
} private static string GetStreamReader(string url, Stream responseStream, Stream requestStream, StreamReader streamReader, WebResponse webResponse, int timeout, string encode, string postData, string contentType)
{
byte[] data = Encoding.GetEncoding(encode).GetBytes(postData);
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
SetAuth(webRequest);
webRequest.Method = "POST";
webRequest.ContentType = contentType + ";" + encode;
webRequest.ContentLength = data.Length;
webRequest.Timeout = timeout;
requestStream = webRequest.GetRequestStream();
requestStream.Write(data, , data.Length);
webResponse = (HttpWebResponse)webRequest.GetResponse();
responseStream = webResponse.GetResponseStream();
if (responseStream == null) { return ""; }
streamReader = new StreamReader(responseStream, Encoding.GetEncoding(encode));
return streamReader.ReadToEnd();
} /// <summary>
/// Post文件流给指定Url
/// </summary>
/// <param name="url">url</param>
/// <param name="filePath">文件路径</param>
/// <returns>响应流字符串</returns>
public static string PostFile(string url, string filePath, string contentType = "application/octet-stream", string encode = "UTF-8")
{
if (!string.IsNullOrEmpty(url) && !string.IsNullOrEmpty(encode) && !string.IsNullOrEmpty(contentType) && !string.IsNullOrEmpty(filePath))
{ Stream requestStream = null;
Stream responseStream = null;
StreamReader streamReader = null;
FileStream fileStream = null;
try
{
// 设置参数
HttpWebRequest webRequest = WebRequest.Create(url) as HttpWebRequest;
SetAuth(webRequest);
webRequest.AllowAutoRedirect = true;
webRequest.Method = "POST";
string boundary = DateTime.Now.Ticks.ToString("X"); // 随机分隔线
webRequest.ContentType = "multipart/form-data;charset=" + encode + ";boundary=" + boundary;
byte[] itemBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n");//消息开始
byte[] endBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");//消息结尾
var fileName = filePath.Substring(filePath.LastIndexOf("/") + );
//请求头部信息
string postHeader = string.Format("Content-Disposition:form-data;name=\"media\";filename=\"{0}\"\r\nContent-Type:{1}\r\n\r\n", fileName, contentType);
byte[] postHeaderBytes = Encoding.UTF8.GetBytes(postHeader);
fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
byte[] fileByteArr = new byte[fileStream.Length];
fileStream.Read(fileByteArr, , fileByteArr.Length);
fileStream.Close();
requestStream = webRequest.GetRequestStream();
requestStream.Write(itemBoundaryBytes, , itemBoundaryBytes.Length);
requestStream.Write(postHeaderBytes, , postHeaderBytes.Length);
requestStream.Write(fileByteArr, , fileByteArr.Length);
requestStream.Write(endBoundaryBytes, , endBoundaryBytes.Length);
requestStream.Close();
responseStream = webRequest.GetResponse().GetResponseStream();//发送请求,得到响应流
if (responseStream == null) return string.Empty;
streamReader = new StreamReader(responseStream, Encoding.UTF8);
return streamReader.ReadToEnd();
}
catch (Exception ex)
{ }
finally
{ }
}
return null; } /// <summary>
/// Get http请求
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="timeout">超时时间</param>
/// <param name="encode">编码</param>
/// <returns>返回单个实体</returns>
public static T GetSingle<T>(string url, int timeout = , string encode = "UTF-8")
{
//HttpWebRequest对象
//HttpClient->dudu 调用预热处理
//Stream—>Model if (!string.IsNullOrEmpty(url) && !string.IsNullOrEmpty(encode))
{
Stream responseStream = null;
StreamReader streamReader = null;
WebResponse webResponse = null;
try
{
string respStr = GetRespStr(url, responseStream, streamReader, webResponse, timeout, encode);
return JsonHelper.JsonDeserialize<T>(respStr);
}
catch (Exception ex)
{ }
finally
{
if (responseStream != null) responseStream.Dispose();
if (streamReader != null) streamReader.Dispose();
if (webResponse != null) webResponse.Dispose();
}
}
return default(T);
} /// <summary>
/// Get http请求
/// </summary>
/// <param name="url"></param>
/// <param name="timeout"></param>
/// <param name="encode"></param>
/// <returns>响应流字符串</returns>
public static string GetResponseString(string url, int timeout = , string encode = "UTF-8")
{
if (!string.IsNullOrEmpty(url) && !string.IsNullOrEmpty(encode))
{
Stream responseStream = null;
StreamReader streamReader = null;
WebResponse webResponse = null;
try
{
return GetRespStr(url, responseStream, streamReader, webResponse, timeout, encode);
}
catch (Exception ex)
{ }
finally
{
if (responseStream != null) responseStream.Dispose();
if (streamReader != null) streamReader.Dispose();
if (webResponse != null) webResponse.Dispose();
}
}
return null;
} private static string GetRespStr(string url, Stream responseStream, StreamReader streamReader, WebResponse webResponse, int timeout, string encode)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Method = "GET";
webRequest.Timeout = timeout;
webResponse = webRequest.GetResponse();
responseStream = webResponse.GetResponseStream();
if (responseStream == null) { return ""; }
streamReader = new StreamReader(responseStream, Encoding.GetEncoding(encode));
return streamReader.ReadToEnd();
}
C#网络编程之Http请求的更多相关文章
-
[深入浅出WP8.1(Runtime)]网络编程之HttpClient类
12.2 网络编程之HttpClient类 除了可以使用HttpWebRequest类来实现HTTP网络请求之外,我们还可以使用HttpClient类来实现.对于基本的请求操作,HttpClient类 ...
-
python3网络编程之socketserver
本节主要是讲解python3网络编程之socketserver,在上一节中我们讲到了socket.由于socket无法支持多用户和多并发,于是就有了socket server. socket serv ...
-
网络编程之UDP编程
网络编程之UDP编程 UDP协议是一种不可靠的网络协议,它在通信的2端各建立一个Socket,但是这个Socket之间并没有虚拟链路,这2个Socket只是发送和接受数据的对象,Java提供了Data ...
-
网络编程之TCP编程
网络编程之TCP编程 前面已经介绍过关于TCP协议的东西,这里不做赘述.Java对于基于TCP协议的网络通信提供了良好的封装,Java使用socket对象来代表两端的通信窗口,并通过Socket产生I ...
-
网络编程之socketserver
网络编程之socketserver """ socketserver.py 中的5个基础类 +------------+ | BaseServer | +-------- ...
-
网络编程之Socket &; ServerSocket
网络编程之Socket & ServerSocket Socket:网络套接字,网络插座,建立网络通信连接至少要一对端口号(socket).socket本质是编程接口(API),对TCP/IP ...
-
GO语言的进阶之路-网络编程之socket
GO语言的进阶之路-网络编程之socket 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是socket; 在说socket之前,我们要对两个概念要有所了解,就是IP和端口 ...
-
网络编程之HttpClient类(转)
12.2 网络编程之HttpClient类 除了可以使用HttpWebRequest类来实现HTTP网络请求之外,我们还可以使用HttpClient类来实现.对于基本的请求操作,HttpClient类 ...
-
[深入浅出Cocoa]iOS网络编程之Socket
http://blog.csdn.net/kesalin/article/details/8798039 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] [深入浅出Co ...
随机推荐
-
Codeforces Round #384 (Div. 2)D-Chloe and pleasant prizes
D. Chloe and pleasant prizes time limit per test 2 seconds memory limit per test 256 megabytes input ...
-
C++ 之 const 随笔记
const关键字,相信对C语言有所了解的同学都应该知道他的作用:1.修饰常量,2.修饰指针,3.修饰函数 1.修饰常量 const修饰后的变量被定义为常量 2.修饰指针 当用const修饰指针的时候, ...
-
Java中long和Long有什么区别 (转载)
“Long is a class. long is a primitive. That means Long can be null, where long can't. Long can go an ...
-
C++_归并排序
//合并有序数组 //合并例子 void MemeryArray(int a[], int n, int b[],int m, int c[]) { int i,j,k; i=j=k=0; while ...
-
[Learn Android Studio 汉化教程]第四章 : Refactoring Code
[Learn Android Studio 汉化教程]第四章 : Refactoring Code 第四章 Refactoring Code 重构代码 在Android Studio中开发,解决 ...
-
实验记录贴 —— 账号同步实验 RTX 和 LDAP(AD域)
目前,公司有多个系统,RTX,邮箱(MD),OA,NC. 这些系统之间,如果要实现单点登录的话,账户肯定需要同步,或者某一种映射机制. 如果所有数据都和*账号数据库(LDAP,这里是AD域)看齐,那 ...
-
VS2010编译、调用Lua程序
一) .建立lua源代码工程,编译lua的静态库 1.下载Lua源码 http://www.lua.org/download.html a 下载后解压到一个目录下,这里假设解压到D:\lua-5.1. ...
-
UVa 11747 - Heavy Cycle Edges
题目大意:计算最小生成树有两种算法:一种是kruskal算法,另一种是与之相反的:如果图中存在环,去掉权重最大的边,直到不存在环.输出去掉的那些边. 可以用kruskal算法解决,在判断一条边时如果加 ...
-
网站开发进阶(二十三)Address already in use: JVM_Bind <;null>;:8088
Address already in use: JVM_Bind <null>:8088 注:请点击此处进行充电! 阿里云服务器又莫名其妙的宕掉!内存泄漏问题依然存在,又出现了端口占用的情 ...
-
Mac 上搭建基于 Hexo + GitHub 个人博客
环境配置 本人电脑系统:macOS Node.js 生成静态页面.安装Node.js Git 用于将本地 Hexo 内容提交到 Github.Xcode自带Git(前提:macOS已经安装了Xcode ...