解析C#網(wǎng)絡(luò)編程中的Http請(qǐng)求
本篇分享簡(jiǎn)單介紹C#中的Http請(qǐng)求,前幾天幫朋友的項(xiàng)目封裝ApiHelper,我粗糙的結(jié)果就如下,想想我真的是差的太遠(yuǎn)了。還有一位架構(gòu)師也在封裝這個(gè)Helper , 所以最后的結(jié)果當(dāng)然是使用大牛的封裝,這篇分享后,準(zhǔn)備學(xué)習(xí)下他的封裝,配置,錯(cuò)誤處理機(jī)制等思想。不過(guò)這次也使我對(duì)C#網(wǎng)絡(luò)編程了解的更多,算是一次學(xué)習(xí)經(jīng)歷吧。真心喜歡和老司機(jī)合作,下一階段將會(huì)持續(xù)跟這位朋友學(xué)習(xí)項(xiàng)目底層的封裝,和他謙虛的態(tài)度,有這樣的機(jī)會(huì)也是幸運(yùn)的。
你可以將其封裝成自己的HttpHelper,經(jīng)朋友建議,統(tǒng)一Http請(qǐng)求的入?yún)⒑统鰠?。在HttpClient方面也參考了dudu的關(guān)于httpclient預(yù)熱的文章。C#中HttpClient使用注意:預(yù)熱與長(zhǎng)連接。
為了做到統(tǒng)一入?yún)⒑统鰠?,定義了Req<T>泛型類(lèi)和Resp<T>泛型類(lèi)。你可以根據(jù)自己的需要進(jìn)行拓展。
public class Req<T>
{
/// <summary>
/// 傳入數(shù)據(jù)
/// </summary>
public T Input { get; set; }
/// <summary>
/// 請(qǐng)求地址
/// </summary>
public string Url { get; set; }
}public class Resp<T>
{
/// <summary>
/// 錯(cuò)誤消息
/// </summary>
public string ErrorMsg { get; set; }
/// <summary>
/// 狀態(tài)碼
/// </summary>
public int StatusCode { get; set; }
/// <summary>
/// 返回?cái)?shù)據(jù)
/// </summary>
public T RespData { get; set; }
}雖然保持了httpClient對(duì)象復(fù)用,但需要注意的是,在設(shè)置了httpClient,并且發(fā)生了一次請(qǐng)求之后,不能再對(duì)其屬性進(jìn)行重新設(shè)置。這也正是我又定義了一個(gè)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 初始化和預(yù)熱 httpClient
_httpClient = new HttpClient();
_httpClient.BaseAddress = new Uri(_baseAddress);
_httpClient.Timeout = TimeSpan.FromMilliseconds(2000);
_httpClient.DefaultRequestHeaders.Add("Accept", "application/json");//application/xml 想Accept的數(shù)據(jù)格式
_httpClient.SendAsync(new HttpRequestMessage
{
Method = new HttpMethod("HEAD"),
RequestUri = new Uri(_baseAddress + "/api/test/HttpClientHot")
})
.Result.EnsureSuccessStatusCode();
#endregion
#region 初始化和預(yù)熱 fileClient
_fileClient = new HttpClient();
_fileClient.BaseAddress = new Uri(_baseAddress + "/api/test/HttpClientHot");
_fileClient.MaxResponseContentBufferSize = 256000;
#endregion
}
/// <summary>
/// http Get請(qǐng)求
/// </summary>
/// <typeparam name="T">入?yún)㈩?lèi)型</typeparam>
/// <typeparam name="TResult">出參類(lèi)型</typeparam>
/// <param name="req">入?yún)?duì)象</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請(qǐng)求
/// </summary>
/// <typeparam name="T">入?yún)㈩?lèi)型</typeparam>
/// <typeparam name="TResult">出參類(lèi)型</typeparam>
/// <param name="req">入?yún)?duì)象</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) };
}
/// 上傳文件
/// <typeparam name="T"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="req"></param>
/// <param name="filePath"></param>
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");//設(shè)置請(qǐng)求頭
// 讀文件流
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");//設(shè)置媒體類(lèi)型
MultipartFormDataContent mulContent = new MultipartFormDataContent("----");//創(chuàng)建用于可傳遞文件的容器
string fileName = filePath.Substring(filePath.LastIndexOf("/") + 1);
mulContent.Add(fileContent, "form", fileName);//第二個(gè)參數(shù)是表單名,第三個(gè)是文件名。
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) };
}
/// 下載
/// <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來(lái)實(shí)現(xiàn)的請(qǐng)求。HttpWebRequest需要你自行設(shè)置很多內(nèi)容,當(dāng)然這也證明其內(nèi)容豐富。下面代碼包含了post,get,以及上傳。
/// <summary>
/// Post Http請(qǐng)求
/// </summary>
/// <param name="url">請(qǐng)求地址</param>
/// <param name="postData">傳輸數(shù)據(jù)</param>
/// <param name="timeout">超時(shí)時(shí)間</param>
/// <param name="contentType">媒體格式</param>
/// <param name="encode">編碼</param>
/// <returns>泛型集合</returns>
public static List<T> PostAndRespList<T>(string url, string postData, int timeout = 5000, 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請(qǐng)求
/// </summary>
/// <param name="url">請(qǐng)求地址</param>
/// <param name="postData">傳輸數(shù)據(jù)</param>
/// <param name="timeout">超時(shí)時(shí)間</param>
/// <param name="contentType">媒體格式</param>
/// <param name="encode">編碼</param>
/// <returns>泛型集合</returns>
public static T PostAndRespSignle<T>(string url, int timeout = 5000, 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請(qǐng)求
/// </summary>
/// <param name="url"></param>
/// <param name="postData"></param>
/// <param name="timeout"></param>
/// <param name="contentType"></param>
/// <param name="encode"></param>
/// <returns>響應(yīng)流字符串</returns>
public static string PostAndRespStr(string url, int timeout = 5000, 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, 0, 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>響應(yīng)流字符串</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
{
// 設(shè)置參數(shù)
HttpWebRequest webRequest = WebRequest.Create(url) as HttpWebRequest;
SetAuth(webRequest);
webRequest.AllowAutoRedirect = true;
webRequest.Method = "POST";
string boundary = DateTime.Now.Ticks.ToString("X"); // 隨機(jī)分隔線
webRequest.ContentType = "multipart/form-data;charset=" + encode + ";boundary=" + boundary;
byte[] itemBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n");//消息開(kāi)始
byte[] endBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");//消息結(jié)尾
var fileName = filePath.Substring(filePath.LastIndexOf("/") + 1);
//請(qǐng)求頭部信息
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, 0, fileByteArr.Length);
fileStream.Close();
requestStream = webRequest.GetRequestStream();
requestStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length);
requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);
requestStream.Write(fileByteArr, 0, fileByteArr.Length);
requestStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
requestStream.Close();
responseStream = webRequest.GetResponse().GetResponseStream();//發(fā)送請(qǐng)求,得到響應(yīng)流
if (responseStream == null) return string.Empty;
streamReader = new StreamReader(responseStream, Encoding.UTF8);
return streamReader.ReadToEnd();
}
catch (Exception ex)
{
}
finally
{
}
}
return null;
}
/// <summary>
/// Get http請(qǐng)求
/// </summary>
/// <param name="url">請(qǐng)求地址</param>
/// <param name="timeout">超時(shí)時(shí)間</param>
/// <param name="encode">編碼</param>
/// <returns>返回單個(gè)實(shí)體</returns>
public static T GetSingle<T>(string url, int timeout = 5000, string encode = "UTF-8")
{
//HttpWebRequest對(duì)象
//HttpClient->dudu 調(diào)用預(yù)熱處理
//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請(qǐng)求
/// </summary>
/// <param name="url"></param>
/// <param name="timeout"></param>
/// <param name="encode"></param>
/// <returns>響應(yīng)流字符串</returns>
public static string GetResponseString(string url, int timeout = 5000, 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();
}到此這篇關(guān)于C#網(wǎng)絡(luò)編程中的Http請(qǐng)求的文章就介紹到這了,更多相關(guān)C#網(wǎng)絡(luò)編程Http請(qǐng)求內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c#基于NVelocity實(shí)現(xiàn)代碼生成
這篇文章主要介紹了c#基于NVelocity實(shí)現(xiàn)代碼生成的方法,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2021-01-01
C#使用StructLayout特性來(lái)控制內(nèi)存結(jié)構(gòu)的操作代碼
在C#中,內(nèi)存布局對(duì)于性能優(yōu)化和與非托管代碼的互操作性至關(guān)重要,StructLayout特性允許開(kāi)發(fā)者控制結(jié)構(gòu)在內(nèi)存中的布局方式,本文給大家介紹了C#使用StructLayout特性來(lái)控制內(nèi)存結(jié)構(gòu)的操作,需要的朋友可以參考下2024-10-10
C# NullReferenceException解決案例講解
這篇文章主要介紹了C# NullReferenceException解決案例講解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
C#使用MD5算法對(duì)密碼進(jìn)行加密的示例代碼
MD5(Message Digest Algorithm 5)是一種被廣泛使用的“消息-摘要算法”,“消息-摘要算法”實(shí)際上就是一個(gè)單項(xiàng)散列函數(shù),數(shù)據(jù)塊經(jīng)過(guò)單向散列函數(shù)得到一個(gè)固定長(zhǎng)度的散列值,本文給大家介紹了C#使用MD5算法對(duì)密碼進(jìn)行加密,需要的朋友可以參考下2024-03-03
C#讀寫(xiě)配置文件方式(config.ini)入門(mén)
這篇文章主要介紹了C#讀寫(xiě)配置文件方式(config.ini)入門(mén),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06

