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 c3p0 配置
spring c3p0 配置 <?xml version="1.0" encoding="UTF-8"?> <beansxmlns=& ...
- hibernate特殊的映射
<property name="update_date" column="update_date" type="java.sql.Timesta ...
- Eigen教程(3)
整理下Eigen库的教程,参考:http://eigen.tuxfamily.org/dox/index.html 矩阵和向量的运算 提供一些概述和细节:关于矩阵.向量以及标量的运算. 介绍 Eige ...
- 插入中国所有省和市的SQL语句--以后用
需要做根据省市过滤查询的,不得已写入数据库,这个留着方便以后用. 首先创建两张表 drop database if exists BSM; create database BSM; use BSM; ...
- 基于jQuery实现的腾讯互动娱乐网站特效
分享一款基于jQuery实现的腾讯互动娱乐网站特效.腾讯互动娱乐网站jQuery特效是一款右侧带伸缩选项卡,支持鼠标滚轮滚动切换特效代码.效果图如下: 在线预览 源码下载 实现的代码. html代 ...
- Web基础 HTML CSS JS JQuery AJAX
1. Web基础 网页的骨骼HTML 什么是HTML超文本标记语言:Hyper Text Markup Language 这都不重要,重要的是:HTML是Web网页的基本组成部分HTML中定义的元素, ...
- java基础解疑!!!
疑问一:0.01+0.09的结果? public class MathTest{ public static void main(String[]args){ double a = 0.01, b = ...
- You have not concluded your merge (MERGE_HEAD exists) git拉取失败
本文转自:http://yijiebuyi.com/blog/5b55eb51ad49ce41e2de9c85dd4513ca.html 今天获取git线上仓库代码报了这个错误: zhangzhi@m ...
- 机器学习----人脸对齐的算法-ASM.AAM..CLM.SDM
引自:http://blog.csdn.net/linolzhang/article/details/55271815 人脸检测 早已比较成熟,传统的基于HOG+线性分类器 的方案检测效果已经相当不错 ...
- Entity Framework 动态构造Lambda表达式Expression<Func<T, bool>>
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; us ...