C#网络编程之Http请求
本片篇分享简单介绍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 ...
随机推荐
- Spring Batch并行与扩展
1. 概述 Spring Batch提供了多种方式用于处理并行,提高性能.主要分为2大类: - 单个进程,多线程 - 多个进程 因此,可以细分为以下几类: - 多线程Step(Multi-thread ...
- C#学习笔记(26)——委托计算器
说明(2017-11-20 15:14:18): 1. 委托一直稀里糊涂的,有人说简单,有人说难,艹你们! 2. 其实主要是因为,平时不用委托也能解决大部分问题,所以都没有特意去用,网上也没有什么很好 ...
- golang深度获取子节点
起因 需要在树形结构里获取子树,树形结构一般是存储一维数组,数组元素里存储子节点的指针 代码 package main import ( "errors" "fmt&qu ...
- [转]Extjs中的迭代方法
原文地址:http://www.veryhuo.com/a/view/36701.html EXTJS 有很多的迭代方法,例如,你也许已知道的Ext.each,但还有另外一些不为人知且很有用的方法.首 ...
- 推荐几个不错的h5游戏引擎
http://www.phaser.io/examples http://www.cocos.com/ http://cn.cocos2d-x.org/tutorial/lists?id=30 coc ...
- java File linux windows 下 绝对路径 相对路径问题
前言 当前项目目录 windows 为 E:\project\testpro\ linux 为 /project/testpro/ Windows环境下获取绝对路径情况 使用 a/b/c 为路径, ...
- kd-tree理论以及在PCL 中的代码的实现
(小技巧记录:博客园编辑的网页界面变小了使用Ctrl ++来变大网页字体) 通过雷达,激光扫描,立体摄像机等三维测量设备获取的点云数据,具有数据量大,分布不均匀等特点,作为三维领域中一个重要的数据来 ...
- python 核心编程 01
特殊变量 python用下划线作为变量的前缀和后缀指定特殊变量._XXX : 不用 'from module import *' 导入, 可以认为是模块中的私有变量__XXX__ : 系统定义的名字_ ...
- 《编程之美》practice
1.2.中国象棋将帅问题 要求:只用一个字节存储变量,输出将帅不照面的所有可能位置. 思路简单,就是穷举让将和帅不在同一列即可,用char高四字节和低四字节分别存储将和帅的位置,位置编号从1到9.代码 ...
- ViewPager一屏显示多个item,及边缘滑动事件优化
关于ViewPager显示两边的item方法,网络上是方法都在ViewPager外包一个Layout, 然后设置ViewPager和外面的Layout的clipChildren="false ...