zoukankan      html  css  js  c++  java
  • .NET C# 使用System.Net.Http下HttpClient执行异步网络数据传输任务

    1. .NET C#可以使用的网络传输方法类库有很多,比如:System.Net.Http.HttpClient、System.Net.WebClient、System.Net.HttpWebRequest和System.Net.HttpWebResponse。

    相关官方文档链接:

    https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=net-5.0

    https://docs.microsoft.com/zh-cn/dotnet/api/system.net.webclient?redirectedfrom=MSDN&view=net-5.0

    https://docs.microsoft.com/zh-cn/dotnet/api/system.net.httpwebrequest?view=net-5.0

    https://docs.microsoft.com/zh-cn/dotnet/api/system.net.httpwebresponse?view=net-5.0

    现在微软官方比较推荐的是使用System.Net.Http.HttpClient来执行网络传输任务。

    2. httpClient异步网络请求工具方法 示例代码如下:

    public static class HttpClientExtensions
        {
            public static Task<HttpResponseMessage> PatchAsync(this HttpClient client, Uri uri, HttpContent content)
            {
                var method = new HttpMethod("PATCH");
                var request = new HttpRequestMessage(method, uri)
                {
                    Content = content
                };
                return client.SendAsync(request);
            }
        }

    public static class ApiHttpUtils
        {
            private static HttpClient _client;

            static ApiHttpUtils()
            {
                //TODO 后续调整为先读取缓存,没有则新建之
                _client = new HttpClient();
            }      

            /// <summary>
            /// 执行http的请求
            /// </summary>
            /// <param name="uri">执行的uri</param>
            /// <param name="methodType">http方法类型</param>
            /// <param name="bodyParam">POSTPUTPatch方式时,传值参数</param>
            /// <param name="inputMediaType">输入格式,即header里面的Content-Type的内容</param>
            /// <param name="outputMediaType">输出格式,即header里面的Accept的内容</param>
            /// <returns>执行结果</returns>
            public static async Task<string> ExecuteHttpClientAsync(
                Uri uri,
                Enums.HttpMethodEnum methodType,
                string bodyParam,
                string inputMediaType = "json",
                string outputMediaType = "json")
            {
                HttpResponseMessage result = null;
                try
                {
                    HttpClient client = CreateHttpClient(outputMediaType);
                    HttpContent content = null;
                    if (!string.IsNullOrWhiteSpace(bodyParam))
                        content = new StringContent(bodyParam, Encoding.UTF8, $"application/{inputMediaType}");
                    switch (methodType)
                    {
                        case Enums.HttpMethodEnum.Post:
                            result = await client.PostAsync(uri, content);
                            break;
                        case Enums.HttpMethodEnum.Put:
                            result = await client.PutAsync(uri, content);
                            break;
                        case Enums.HttpMethodEnum.Get:
                            result = await client.GetAsync(uri);
                            break;
                        case Enums.HttpMethodEnum.Delete:
                            result = await client.DeleteAsync(uri);
                            break;
                        case Enums.HttpMethodEnum.Patch:
                            result = await client.PatchAsync(uri, content);
                            break;
                    }
                }
                catch (AggregateException ex)
                {
                    #region 获取线程异常信息
                    Exception firstException = null;
                    if (ex.InnerExceptions != null && ex.InnerExceptions.Any())
                    {
                        firstException = ex.InnerExceptions.First();
                        if (firstException.InnerException != null)
                            firstException = firstException.InnerException;
                    }

                    //Logger.LogException(firstException);//Nlog日志记录
                    #endregion 获取线程异常信息
                    result = new HttpResponseMessage(HttpStatusCode.InternalServerError)
                    {
                        Content =
                            new StringContent(firstException != null
                                ? firstException.ToString()
                                : "Encountered an AggreggateException without any inner exceptions")
                    };
                }
                catch (Exception ex)
                {
                    //Logger.LogException(ex);//Nlog日志记录
                    result = new HttpResponseMessage(HttpStatusCode.InternalServerError)
                    {
                        Content =
                            new StringContent("Encountered an AggreggateException without any inner exceptions")
                    };
                }
                return await result.Content.ReadAsStringAsync();
            }

            /// <summary>
            /// 创建http的客户端
            /// </summary>
            /// <param name="outputMediaType">输出格式,即header里面的Accept的内容</param>
            public static HttpClient CreateHttpClient(string outputMediaType = "json")
            {
                HttpClient client = _client;
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(
                    new MediaTypeWithQualityHeaderValue($"application/{outputMediaType}"));
                return client;
            }
        }

    3.Client调用方式如下,以WinForm窗体程序举例,某按钮点击事件后台方法:

        public class InspectContentExtractReturnInputModel
        {
            public List<string> Datas { get; set; }
        }

    public static class SystemConfig
        {
            /// <summary>
            /// 测试调用异步耗时webAPI不等待其返回值
            /// </summary>
            public static string TestTimeConsumWebApiUrl { get; set; }

            public static void LoadSettings()
            {
                try
                {
                    TestTimeConsumWebApiUrl = ConfigUtils.GetAppSetting("TestTimeConsumWebApiUrl");
                }
                catch (Exception ex)
                {
                }
            }
        }

        public enum ResponseStatusEnum
        {
            /// <summary>
            /// 程序执行正常,code 200
            /// </summary>
            Ok = 200,
            /// <summary>
            /// 参数为null或为空,code 201
            /// </summary>
            ArgumentsIsNull = 201,
            /// <summary>
            /// 程序执行发生异常,code 202
            /// </summary>
            ProgramExecuteOccurException = 202
        }

    [Description("响应信息")]
        public class Response<T>
        {
            /// <summary>
            /// 错误码,默认200
            /// 200正常,201参数为空,202程序执行异常
            /// </summary>
            [Description("错误码")]
            public string ErrorCode { get; set; } = ((int)ResponseStatusEnum.Ok).ToString();

            [Description("错误信息")]
            public string ErrorMsg { get; set; } = "";

            [Description("响应结果是否成功")]
            public bool IsSuccess
            {
                get { return string.IsNullOrWhiteSpace(this.ErrorMsg); }
            }

            [Description("结果集合")]
            public T Data { get; set; }

        }

    public class InspectSwitchViewModel<T>
        {
            public T Result { get; set; }
        }

    public partial class Form2 : Form
        {
            //Api input model
            private InspectContentExtractReturnInputModel _inputModel = new InspectContentExtractReturnInputModel();
            public Form2()
            {
                InitializeComponent();
            }

            private void button1_Click(object sender, EventArgs e)
            {
                _inputModel = new InspectContentExtractReturnInputModel()
                {
                    Datas = new List<string>()
                    {
                        "params1","params2","params3"
                    }
                };

                Task.Run(async () =>
                {
                    var r = await ApiHttpUtils.ExecuteHttpClientAsync(
                        new Uri(SystemConfig.TestTimeConsumWebApiUrl),//server api url
                        HttpMethodEnum.Post, //http method type
                        DataTransferExtensions.SetTransferDataJson(_inputModel), //input model 序列为json
                        "json",//input params type:json
                        "json"//return params type:json
                        );
                    //以下是与服务端预定好的返回值数据结构,将json反序列化为Model
                    var response = DataTransferExtensions.GetTransferData<Response<InspectSwitchViewModel<object>>>(r);
                    if (response.IsSuccess &&
                        response.ErrorCode == ((int) ResponseStatusEnum.Ok).ToString())//判断服务端响应结果
                    {
                        this.Invoke(new Action(() =>
                        {
                            this.label1.Text = response.Data.Result.ToString();//更新winform 界面UI提示信息
                        }));
                    }
                    else
                    {
                        this.Invoke(new Action(() =>
                        {
                            this.label1.Text = response.ErrorMsg;//更新winform 界面UI提示信息
                        }));
                    }
                });
            }
        }

    4.Server是使用的ASP.NET WebAPI,示例代码如下:

    public class InspectSwitchControllerService
        {
            public async Task<Response<InspectSwitchViewModel<object>>> InspectContentExtractReturn(List<string> datas)
            {
                Response<InspectSwitchViewModel<object>> r = new Response<InspectSwitchViewModel<object>>();
                try
                {
                    //await Task.Delay(1000000);//此处编写业务实现代码
                }
                catch (Exception ex)
                {
                    r.ErrorCode = ((int) ResponseStatusEnum.ProgramExecuteOccurException).ToString();
                    r.ErrorMsg = ex.Message;
                }
                return r;
            }
        }

    public class InspectSwitchController : ApiController
        {
            private readonly InspectSwitchControllerService _inspectSwitchControllerService = new InspectSwitchControllerService();

            [HttpPost]
            public IHttpActionResult InspectContentExtractReturn([FromBody] InspectContentExtractReturnInputModel model)
            {
                var response = new Response<InspectSwitchViewModel<object>>()
                {
                    ErrorCode = ((int)ResponseStatusEnum.Ok).ToString(),
                    ErrorMsg = string.Empty,
                    Data = new InspectSwitchViewModel<object>(){Result= "调用成功,直接返回结果,不等待耗时任务完成即返回" }
                };

                Task.Run(async () =>
                {
                    await _inspectSwitchControllerService.InspectContentExtractReturn(model.Datas);
                });

                return Ok(response);
            }
        }

  • 相关阅读:
    PowerDesigner中生成SQL SERVER2005字段注释 和导出图片的方法
    右键显示打开控制台
    dubbo 的 Protocol 类
    nacos 的 grpc
    shell 替换文本中 为空格,多行为本合并为一行
    gcc、python3、python性能分析工具安装
    kafka listeners和advertised
    Default Activity not found 问题解决
    使用Global Mapper计算kml中面状图形的面积
    jeecg-boot 报表组——折线图初始化显示部分图例,部分变灰
  • 原文地址:https://www.cnblogs.com/jeff151013/p/14704576.html
Copyright © 2011-2022 走看看