HttpClient 常規用法

HttpClient

發送請求

其他請求同Post

Get

HttpClient client= new HttpClient();
//添加請求頭
client.DefaultRequestHeaders.Add("Key", "Value");
//請求頭添加其他值
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "");
client.DefaultRequestHeaders.Connection.Add(new("Keep-Alive"));
client.DefaultRequestHeaders.UserAgent.Add(new("Opera/8.0 (Macintosh; PPC Mac OS X; U; en)"));
client.DefaultRequestHeaders.Accept.Add(new ("text/html"));
client.DefaultRequestHeaders.AcceptCharset.Add(new ("utf-8"));
client.DefaultRequestHeaders.AcceptEncoding.Add(new ("gzip,deflate"));
client.DefaultRequestHeaders.AcceptLanguage.Add(new ("zh-CN,fr-FR;q=0.5"));

//同步
client.GetAsync("https://www.baidu.com").Result;
//異步
var response = await client.GetAsync("https://www.baidu.com");

Post

JSON請求

HttpClient client = new HttpClient();
string jsonBody = "{\"beijing\":{\"zone\":\"海淀\",\"zone_en\":\"haidian\"}}";
HttpContent content = new StringContent(jsonBody, System.Text.Encoding.UTF8);

//指定請求頭ContentType,其他類型需要變更ContentType
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json") { CharSet = "utf-8" };
            
//添加請求頭
content.Headers.Add("Key", "Value");
content.Headers.Add("Authorization", "token");
content.Headers.Add("Connection", "Keep-Alive");
content.Headers.Add("Accept", "text/html");
content.Headers.Add("Accept-Charset", "utf-8");
content.Headers.Add("Accept-Encoding", "gzip,deflate");
content.Headers.Add("Accept-Language", "zh-CN,fr-FR;q=0.5");
content.Headers.Add("User-Agent", "Opera/8.0 (Macintosh; PPC Mac OS X; U; en)");
var response = await client.PostAsync("https://www.baidu.com", content);

Form表單

HttpClient client = new HttpClient();
Dictionary<string, string> dict = new Dictionary<string, string>();
dict.Add("email", "email");
dict.Add("pwd", "pwd");
var formContent = new FormUrlEncodedContent(dict);
string reqBody = await formContent.ReadAsStringAsync();
HttpContent content = new StringContent(reqBody, System.Text.Encoding.UTF8);
//指定請求頭ContentType,其他類型需要變更ContentType
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded") { CharSet = "utf-8" };
var response = await client.PostAsync("https://www.baidu.com", content);

上傳文件/鍵值對Body

HttpClient client = new HttpClient();
var content = new MultipartFormDataContent();
content.Add(new StringContent("value"), "key");
byte[] File = null;
content.Add(new ByteArrayContent(File), "argName","FileName");
//指定請求頭ContentType,其他類型需要變更ContentType
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("multipart/form-data") { CharSet = "utf-8" };
var response = await client.PostAsync("https://www.baidu.com", content);

上傳文件二進制流/Binary

HttpClient client = new HttpClient();
System.IO.Stream stream = null;
HttpContent content=new StreamContent(stream);
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream") { CharSet = "utf-8" };
var response = await client.PostAsync("https://www.baidu.com", content);

添加請求頭認證

string username = "admin";
string pwd = "123";
string basicAuthorization = $"{username}:{pwd}";

//爲request添加basic授權憑據
if (string.IsNullOrWhiteSpace(basicAuthorization) == false)
{
    var byteArray = Encoding.ASCII.GetBytes(basicAuthorization);
    client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
}

string bearerAuthorization = string.Empty;
//爲request添加bearer授權憑證
if (string.IsNullOrWhiteSpace(bearerAuthorization) == false)
{
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearerAuthorization);
}

代理

var httpClientHandler = new HttpClientHandler()
{
    //Proxy = new WebProxy("ProxyUri"),
    Proxy = new WebProxy()
    {
        Address = new Uri("ProxyUri"),
        BypassProxyOnLocal = false,
        UseDefaultCredentials = false,
        //服務器賬號密碼認證
        Credentials = new NetworkCredential("userName", "password")
    },
    UseProxy = true
};
HttpClient client = new HttpClient(httpClientHandler);

響應結果處理

//判斷是否成功
if (response.IsSuccessStatusCode) { }

//獲取響應編碼
var responseStatusCodes = response.StatusCode;

//獲取響應頭
var responseHeaders = response.Headers;
var headersList = responseHeaders.GetValues("Set-Cookie").ToList();
string token = headersList.FirstOrDefault(a => a.Contains("token"));
List<KeyValuePair<string, string>> list = new();
foreach (var header in response.Headers.ToList())
{
    foreach (var value in header.Value)
    {
        list.Add(new KeyValuePair<string, string>(header.Key, value));
    }
}

//獲取響應結果
var responseContent = await response.Content.ReadAsStringAsync();

//獲取響應流
var responseStream = await response.Content.ReadAsStreamAsync();

NetCore中使用IHttpClientFactory

註冊HttpClient

//6.0-Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient();

//5.0-Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient();
}

Controller中構造函數注入

using Microsoft.AspNetCore.Mvc;

namespace WebApplication1.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private readonly IHttpClientFactory _httpClientFactory;

        public WeatherForecastController(IHttpClientFactory httpClientFactory)
        {
            _httpClientFactory = httpClientFactory;
        }

        [HttpGet]
        public string Get()
        {
            var client = _httpClientFactory.CreateClient();
            var response = client.GetAsync("https://www.baidu.com").Result;
            var responseContent = response.Content.ReadAsStringAsync().Result;
            return responseContent;
        }
    }
}

ABP中注入

public IHttpClientFactory HttpClientFactory => LazyServiceProvider.LazyGetRequiredService<IHttpClientFactory>();

HttpClientHelper

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Security;
using System.Text;
using System.Threading.Tasks;

namespace Helper
{
    public class HttpClientHelper
    {
        private readonly IHttpClientFactory _httpClientFactory;

        public HttpClientHelper(IHttpClientFactory httpClientFactory)
        {
            _httpClientFactory = httpClientFactory;
        }

        /// <summary>
        /// Get請求
        /// </summary>
        /// <param name="url">請求地址</param>
        /// <param name="arg">get請求url參數</param>
        /// <param name="headerDic">請求頭</param>
        /// <returns></returns>
        public async Task<ResponseResult> DoGet(string url, IDictionary<string, string> arg = null,
            IDictionary<string, string> headerDic = null, HttpClientHandler handler = null)
        {
            //構造參數
            var requestUrl = url;
            if (arg != null && arg.Count > 0)
            {
                string argStr = url.Contains("?") ? "&" : "?";
                foreach (var item in arg)
                {
                    argStr += item.Key + "=" + item.Value + "&";
                }
                argStr = argStr.TrimEnd('&');
                requestUrl = url + argStr;
            }

            using var client = handler == null ? _httpClientFactory.CreateClient() : new HttpClient(handler);

            //構造請求頭
            if (headerDic != null)
            {
                foreach (var item in headerDic)
                {
                    client.DefaultRequestHeaders.Add(item.Key, item.Value);
                }
            }

            using var response = await client.GetAsync(requestUrl).ConfigureAwait(false);
            var result = await ReadResponseResult(response).ConfigureAwait(false);
            return result;
        }

        /// <summary>
        /// Post請求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="reqBody"></param>
        /// <param name="headerDic"></param>
        /// <returns></returns>
        public async Task<ResponseResult> DoPost(string url, string reqBody,
            Dictionary<string, string> headerDic = null, HttpClientHandler handler = null)
        {
            return await DoRequest(url, new StringContent(reqBody, Encoding.UTF8), headerDic, HttpMethod.Post, RequestFormat.Json, handler);
        }

        /// <summary>
        /// XML Post請求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="reqBody"></param>
        /// <param name="headerDic"></param>
        /// <returns></returns>
        public async Task<ResponseResult> DoXmlPost(string url, string reqBody, Dictionary<string, string> headerDic = null)
        {
            return await DoRequest(url, new StringContent(reqBody, Encoding.UTF8), headerDic, HttpMethod.Post, RequestFormat.Xml);
        }

        /// <summary>
        /// Text Post請求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="reqBody"></param>
        /// <param name="headerDic"></param>
        /// <returns></returns>
        public async Task<ResponseResult> DoTextPost(string url, string reqBody, Dictionary<string, string> headerDic = null)
        {
            return await DoRequest(url, new StringContent(reqBody, Encoding.UTF8), headerDic, HttpMethod.Post, RequestFormat.Text);
        }

        /// <summary>
        /// 提交Form Post請求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="fromData"></param>
        /// <param name="headerDic"></param>
        /// <returns></returns>
        public async Task<ResponseResult> DoFormPost(string url,
            Dictionary<string, string> fromData, Dictionary<string, string> headerDic = null, HttpClientHandler handler = null)
        {
            var content = new FormUrlEncodedContent(fromData);
            string reqBody = await content.ReadAsStringAsync();
            return await DoRequest(url, new StringContent(reqBody, Encoding.UTF8), headerDic, HttpMethod.Post, RequestFormat.Form, handler);
        }

        /// <summary>
        /// Stream請求
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public async Task<ResponseResult> DoStreamRequest(string url,
          HttpMethod httpMethod,
          StreamContent streamContent,
          Dictionary<string, string> headerDic = null,
          HttpClientHandler handler = null)
        {
            return await DoRequest(url, streamContent, headerDic, httpMethod, RequestFormat.Stream, handler);
        }

        /// <summary>
        /// 上傳File請求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="bodyDic">Body參數</param>
        /// <param name="filelist">文件參數:文件流/參數名稱/文件名稱</param>
        /// <param name="headerDic">請求頭</param> 
        /// <param name="handler">HttpClientHandler</param> 
        /// <param name="boundary">邊界符</param> 
        /// <returns></returns>
        public async Task<ResponseResult> DoFileRequest(string url,
            HttpMethod httpMethod,
            Dictionary<string, string> bodyDic,
            List<Tuple<byte[], string, string>> filelist,
            Dictionary<string, string> headerDic = null,
            HttpClientHandler handler = null,
            string boundary = "")
        {
            var content = new MultipartFormDataContent();
            if (bodyDic != null)
            {
                foreach (var item in bodyDic)
                {
                    content.Add(new StringContent(item.Value), item.Key);
                }
            }

            if (filelist != null)
            {
                foreach (var item in filelist)
                {
                    content.Add(new ByteArrayContent(item.Item1), item.Item2, item.Item3);
                }
            }

            return await DoRequest(url, content, headerDic, httpMethod, RequestFormat.MultipartForm, handler, boundary);
        }

        /// <summary>
        /// Put請求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postJson"></param>
        /// <param name="headerDic"></param>
        /// <returns></returns>
        public async Task<ResponseResult> DoPut(string url, string postJson, Dictionary<string, string> headerDic = null)
        {
            return await DoRequest(url, new StringContent(postJson, Encoding.UTF8), headerDic, HttpMethod.Put).ConfigureAwait(false);
        }

        /// <summary>
        /// Delete請求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postJson"></param>
        /// <param name="headerDic"></param>
        /// <returns></returns>
        public async Task<ResponseResult> DoDelete(string url, string postJson, Dictionary<string, string> headerDic = null)
        {
            return await DoRequest(url, new StringContent(postJson, Encoding.UTF8), headerDic, HttpMethod.Delete).ConfigureAwait(false);
        }

        /// <summary>
        /// POST,PUT,DELETE請求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="reqBody"></param>
        /// <param name="headerDic"></param>
        /// <param name="httpMethod"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        private async Task<ResponseResult> DoRequest(string url, HttpContent content, Dictionary<string, string> headerDic,
            HttpMethod httpMethod, RequestFormat contentType = RequestFormat.Json, HttpClientHandler handler = null, string boundary = "")
        {
            //handler ??= new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip };
            HttpResponseMessage response;
            string contentTypeStr = GetContentType(contentType, boundary);

            content.Headers.ContentType = new MediaTypeHeaderValue(contentTypeStr) { CharSet = "utf-8" };
            if (headerDic != null)
            {
                foreach (var item in headerDic)
                {
                    content.Headers.Add(item.Key, item.Value);
                }
            }

            using var client = handler == null ? _httpClientFactory.CreateClient() : new HttpClient(handler);

            if (content is StringContent && httpMethod.Equals(HttpMethod.Delete))
            {
                if (string.IsNullOrWhiteSpace(await content.ReadAsStringAsync()))
                {
                    if (headerDic != null)
                        foreach (var item in headerDic)
                            client.DefaultRequestHeaders.Add(item.Key, item.Value);
                    response = await client.DeleteAsync(url).ConfigureAwait(false);
                    return await ReadResponseResult(response).ConfigureAwait(false);
                }
            }

            var message = new HttpRequestMessage
            {
                Method = httpMethod,
                Content = content,
                RequestUri = new Uri(url)
            };           
            response = await client.SendAsync(message).ConfigureAwait(false);
            return await ReadResponseResult(response).ConfigureAwait(false);
        }

        /// <summary>
        /// 獲取響應頭List
        /// </summary>
        /// <param name="headers"></param>
        /// <returns></returns>
        public List<KeyValuePair<string, string>> GetHttpResponseHeadersList(HttpResponseHeaders headers)
        {
            List<KeyValuePair<string, string>> list = new();
            foreach (var header in headers.ToList())
                foreach (var value in header.Value)
                    list.Add(new KeyValuePair<string, string>(header.Key, value));

            return list;
        }

        /// <summary>
        /// 讀取請求結果
        /// </summary>
        /// <param name="response"></param>
        /// <returns></returns>
        private async Task<ResponseResult> ReadResponseResult(HttpResponseMessage response)
        {
            var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
            var result = new ResponseResult(response.StatusCode, content, response.Headers);
            return result;
        }

        /// <summary>
        /// content type
        /// </summary>
        /// <param name="type"></param>
        /// <param name="boundary">邊界符</param>
        /// <returns></returns>
        private static string GetContentType(RequestFormat type, string boundary = "")
        {
            string typeStr = "";
            switch (type)
            {
                case RequestFormat.Json:
                    typeStr = "application/json";
                    break;
                case RequestFormat.Form:
                    typeStr = "application/x-www-form-urlencoded";
                    break;
                case RequestFormat.MultipartForm:
                    var tempboundary = string.IsNullOrWhiteSpace(boundary) == false
                        ? boundary : DateTime.Now.Ticks.ToString("x");
                    typeStr = "multipart/form-data; boundary=" + tempboundary;
                    break;
                case RequestFormat.Stream:
                    typeStr = "application/octet-stream";
                    break;
                case RequestFormat.Xml:
                    typeStr = "application/xml";
                    break;
                case RequestFormat.TextXml:
                    typeStr = "text/xml";
                    break;
                case RequestFormat.Text:
                    typeStr = "text/plain";
                    break;
            }
            return typeStr;
        }
    }

    /// <summary>
    ///響應的結果
    /// </summary>
    public class ResponseResult
    {
        /// <summary>
        /// http狀態碼
        /// </summary>
        public HttpStatusCode HttpStatus { get; set; }

        /// <summary>
        /// 內容
        /// </summary>
        public string Content { get; set; }

        /// <summary>
        /// http響應請求頭
        /// </summary>
        public HttpResponseHeaders Headers { get; set; }

        /// <summary>
        /// 獲取請求是否成功
        /// </summary>
        public bool IsSuccess
        {
            get
            {
                var statusCode = (int)HttpStatus;
                return statusCode >= 200 && statusCode < 400;
            }
        }

        /// <summary>
        /// 構造Json響應結果
        /// </summary>
        /// <param name="httpStatus"></param>
        /// <param name="content"></param>
        public ResponseResult(HttpStatusCode httpStatus, string content, HttpResponseHeaders headers)
        {
            if ((int)httpStatus >= 300)
            {
                throw new Exception("請求失敗:" + content + (int)httpStatus);
            }
            HttpStatus = httpStatus;
            Content = content;
            Headers = headers;
        }
    }

    /// <summary>
    /// 請求類型的枚舉
    /// </summary>
    enum RequestFormat
    {
        /// <summary>
        /// json格式
        /// </summary>
        Json,

        /// <summary>
        /// form格式
        /// </summary>
        Form,

        /// <summary>
        /// 多內容的form格式
        /// </summary>
        MultipartForm,

        /// <summary>
        /// 流的格式
        /// </summary>
        Stream,

        /// <summary>
        ///xml格式 
        /// </summary>
        Xml,

        /// <summary>
        /// textxml
        /// </summary>
        TextXml,

        /// <summary>
        /// Text
        /// </summary>
        Text
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章