C# abp框架Http辅助类

科技资讯 投稿 24500 0 评论

C# abp框架Http辅助类

一、定义接口

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;

namespace Test.Common
{
    /// <summary>
    /// HTTP请求接口
    /// </summary>
    public interface IHttpClientUtils: IApplicationService
    {
        /// <summary>
        /// 发送HTTP请求,注意Get请求第4个参数才是缓存key,因此第3个参数请设置为null
        /// </summary>
        /// <param name="method">HttpMethod.Get、HttpMethod.Post、HttpMethod.Put、HttpMethod.Delete</param>
        /// <param name="url">完整地址</param>
        /// <param name="model">请求体对象</param>
        /// <param name="cacheKey">鉴权请求头缓存key</param>
        /// <param name="headers">请求头</param>
        /// <returns></returns>
        Task<T> SendAsync<T>(HttpMethod method, string url, object model = null, string cacheKey = "", Dictionary<string, string> headers = null;


        /// <summary>
        /// 发送HTTP表单请求
        /// </summary>
        /// <param name="method">HttpMethod.Post、HttpMethod.Put</param>
        /// <param name="url">完整地址</param>
        /// <param name="model">请求体对象</param>
        /// <param name="cacheKey">鉴权请求头缓存key</param>
        /// <param name="headers">请求头</param>
        /// <returns></returns>
        Task<T> SendFormAsync<T>(HttpMethod method, string url, object model, string cacheKey = "", Dictionary<string, string> headers = null;
    }
}

二、实现接口

1、支持https

3、支持对象携带文件上传

using Microsoft.Extensions.Logging; using Newtonsoft.Json; using RestSharp; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Net.Security; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading.Tasks; using Volo.Abp.Application.Services; using Volo.Abp.Caching; using Volo.Abp.Json; namespace Test.Common { /// <summary> /// HTTP请求实现 /// </summary> public class HttpClientUtils: ApplicationService, IHttpClientUtils { private readonly ILogger<HttpClientUtils> _logger; private readonly IDistributedCache<Dictionary<string, string>> _cache; public HttpClientUtils( ILogger<HttpClientUtils> logger, IDistributedCache<Dictionary<string, string>> cache { _cache = cache; _logger = logger; } /// <summary> /// 发送HTTP请求 /// </summary> /// <param name="method">HttpMethod.Get、HttpMethod.Post、HttpMethod.Put、HttpMethod.Delete</param> /// <param name="url">完整地址</param> /// <param name="model">请求体对象</param> /// <param name="cacheKey">鉴权请求头缓存key</param> /// <param name="headers">请求头</param> /// <returns></returns> public async Task<T> SendAsync<T>(HttpMethod method, string url, object model = null, string cacheKey = "", Dictionary<string, string> headers = null { _logger.LogInformation($"SendAsync {method.Method} url = {url},cacheKey = {cacheKey},data = {JsonConvert.SerializeObject(model}"; try { using (var client = new HttpClient( { if (!url.StartsWith("http", StringComparison.OrdinalIgnoreCase { url = $"http://{url}"; } using (var request = new HttpRequestMessage(method, url { if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase { SetHttps(; } var sc = new StreamContent(new MemoryStream(; if (model != null { var jsonStr = JsonConvert.SerializeObject(model; var bytes = Encoding.UTF8.GetBytes(jsonStr; sc = new StreamContent(new MemoryStream(bytes; } HeaderHandler(request, sc.Headers, "application/json", headers, cacheKey; request.Content = sc; var rsp = await client.SendAsync(request; return ResponseHandler<T>(rsp; } } } catch (Exception e { _logger.LogError($"SendAsync {method.Method} 请求:{url}, 错误消息:{e.Message}, 请求参数:{JsonConvert.SerializeObject(model}"; throw new Exception($"请求HTTP服务{new Uri(url.AbsolutePath}异常:{e.Message}"; } } /// <summary> /// 发送HTTP表单请求 /// </summary> /// <param name="method">HttpMethod.Post、HttpMethod.Put</param> /// <param name="url">完整地址</param> /// <param name="model">请求体对象</param> /// <param name="cacheKey">鉴权请求头缓存key</param> /// <param name="headers">请求头</param> /// <returns></returns> public async Task<T> SendFormAsync<T>(HttpMethod method, string url, object model, string cacheKey = "", Dictionary<string, string> headers = null { _logger.LogInformation($"SendFormAsync {method.Method} url = {url},cacheKey = {cacheKey},data = {JsonConvert.SerializeObject(model}"; try { var client = new RestClient(; var request = new RestRequest(url, Method.POST; if (method == HttpMethod.Put { request.Method = Method.PUT; } SetHeader(request, cacheKey, headers; request.AlwaysMultipartFormData = true; var props = model.GetType(.GetProperties(; foreach (var item in props { var k = item.Name; var v = item.GetValue(model; if (v == null { _logger.LogInformation($"SendFormAsync {method.Method} url = {url} {k} value is null"; continue; } if (v.GetType(.Name == "Dictionary`2" // 文件只支持字典类型 { if (v is Dictionary<string, byte[]> { var files = v as Dictionary<string, byte[]>; foreach (var obj in files // 多个文件只能一个个添加,不能集合到List中 { string ext = Path.GetExtension(obj.Key; ext = ext.RemovePreFix("."; _logger.LogInformation($"SendFormAsync file key = {k}, name = {obj.Key}, ext = {ext}, size = {obj.Value.Length}"; request.AddFileBytes(k, obj.Value, obj.Key, $"image/{ext}"; } } } else { request.AddParameter(k, v; } } var response = await client.ExecuteAsync(request; if (response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.Created { _logger.LogError($"SendFormAsync {method.Method} {url} 响应失败: {response.Content}"; throw new Exception($"服务器响应失败:status = {response.StatusCode}"; } _logger.LogInformation($"SendFormAsync {method.Method} {url} Response: {response.Content}"; return JsonConvert.DeserializeObject<T>(response.Content, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }; } catch (Exception e { _logger.LogError($"SendFormAsync {method.Method} 请求:{url}, 错误消息:{e.Message}, 请求参数:{JsonConvert.SerializeObject(model}"; throw new Exception($"请求HTTP服务{new Uri(url.AbsolutePath}异常:{e.Message}"; } } /// <summary> /// 设置请求头 /// </summary> /// <param name="request"></param> /// <param name="cacheKey"></param> private void SetHeader(RestRequest request, string cacheKey, Dictionary<string, string> headers { // 鉴权请求头 var cacheHeaders = _cache.Get(cacheKey; if (cacheHeaders != null { foreach (var dic in cacheHeaders { _logger.LogInformation($"SetHeader cache header: {dic.Key} = {dic.Value}"; if (dic.Key.Equals("authorization", StringComparison.OrdinalIgnoreCase { request.AddHeader("Authorization", dic.Value; } else { request.AddHeader(dic.Key, dic.Value; } } } // 默认请求头 if (headers != null && headers.Count > 0 { foreach (var dic in headers { request.AddHeader(dic.Key, dic.Value; } } } /// <summary> /// 处理请求头 /// </summary> /// <param name="request">new HttpRequestMessage</param> /// <param name="contentHeader">new MultipartFormDataContent</param> /// <param name="contentType">multipart/form-data</param> /// <param name="headers">Dictionary<string, string></param> /// <param name="cacheKey">authorization</param> private void HeaderHandler(HttpRequestMessage request, HttpContentHeaders contentHeader, string contentType, Dictionary<string, string> headers, string cacheKey { // 添加默认请求头 if (headers != null && headers.ContainsKey("Content-Type" { contentType = headers["Content-Type"]; } if (string.IsNullOrEmpty(contentType { contentType = "application/json"; // 默认application/json } _logger.LogInformation($"HeaderHandler {request.Method.Method} {request.RequestUri.AbsolutePath} default contentType header: {contentType}"; if (contentType.IndexOf("multipart/form-data" != -1 { contentHeader.Remove("Content-Type"; // MediaTypeHeaderValue不支持解析boundary,所以先删除再Add contentHeader.TryAddWithoutValidation("Content-Type", contentType; } else { contentHeader.ContentType = new MediaTypeHeaderValue(contentType; } // 添加鉴权请求头 var cacheHeaders = _cache.Get(cacheKey; if (cacheHeaders != null { foreach (var dic in cacheHeaders { _logger.LogInformation($"HeaderHandler {request.Method.Method} {request.RequestUri.AbsolutePath} cache header: {dic.Key} = {dic.Value}"; if (dic.Key.Equals("authorization", StringComparison.OrdinalIgnoreCase { request.Headers.Authorization = new AuthenticationHeaderValue(dic.Value; // request.SetBearerToken(dic.Value; // 这个方法里加了前缀Bearer,针对接口不同 } else { contentHeader.Add(dic.Key, dic.Value; // cookie、token ... } } } // 添加参数请求头 if (headers != null && headers.Count > 0 { foreach (var dic in headers { if (contentHeader.ContentType.MediaType == dic.Value { continue; } contentHeader.Add(dic.Key, dic.Value; } } } /// <summary> /// 处理HTTP响应 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="rsp"></param> /// <returns></returns> /// <exception cref="Exception"></exception> private T ResponseHandler<T>(HttpResponseMessage rsp { if (rsp.StatusCode != HttpStatusCode.OK && rsp.StatusCode != HttpStatusCode.Created { _logger.LogError($"ResponseHandler {rsp.RequestMessage.Method.Method} {rsp.RequestMessage.RequestUri.AbsoluteUri} 响应失败: {rsp.Content.ReadAsStringAsync(.Result}"; throw new Exception($"服务器响应失败:status = {rsp.StatusCode}"; } if (rsp is T { return (T(objectrsp; // 返回HttpResponseMessage,用于获取响应头 } else { var json = rsp.Content.ReadAsStringAsync(.Result; _logger.LogInformation($"ResponseHandler {rsp.RequestMessage.Method.Method} {rsp.RequestMessage.RequestUri.AbsoluteUri} 响应:{json}"; return JsonConvert.DeserializeObject<T>(json, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }; // return rsp.Content.ReadFromJsonAsync<T>(.Result; // 会检查int null类型报错 } } /// <summary> /// 设置HTTPS /// </summary> private void SetHttps( { // set remote certificate Validation auto pass ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(RemoteCertificateValidate; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; // FIX:修复不同.Net版对一些SecurityProtocolType枚举支持情况不一致导致编译失败等问题,这里统一使用数值 //ServicePointManager.SecurityProtocol = (SecurityProtocolType48 | (SecurityProtocolType3072 | (SecurityProtocolType768 | (SecurityProtocolType192; } /// <summary> /// 远程证书验证 /// </summary> /// <param name="sender"></param> /// <param name="cert"></param> /// <param name="chain"></param> /// <param name="error"></param> /// <returns>验证是否通过,始终通过</returns> private bool RemoteCertificateValidate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error { return true; } } }

三、遇到问题

1、无法添加请求头content-type

s.Headers.Add("Content-Type", ""
报错:Misused header name, 'Content-Type'. Make sure request headers are used with HttpRequestMessage,

b.Add("Content-Type", ""
报错:Cannot add value because header 'Content-Type' does not support multiple values。

b.ContentType = new MediaTypeHeaderValue("multipart/form-data; boundary=----8db27a5c21ea4f8";
报错:The format of value 'multipart/form-data; boundary=----8db27a5c21ea4f8' is invalid
报错:'multipart/form-data; ----8db27a507065123' is invalid
报错:'multipart/form-data; boundary=--8db27ca4cfafb57' is invalid

请看方法:HeaderHandler

 

编程笔记 » C# abp框架Http辅助类

赞同 (127) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽