• .net core webApi 添加各种中间件-会一直补充


    一、为什么使用中间件

    在我们很多时候,当一个请求过来之后,我们想对这个请求做各种各样的操作和记录,这个时候我们可以加入中间件

    目的就是对这个请求和响应做处理,其实不难理解,这就是类似于工业机器,一个商品出来之前会有很多关卡,会执行N到工序,

    最后加工出来的产品就是我们想要的,也是安全的。这些关卡就类似于中间件的作用了。

    核心就是一系列的请求委托,Run、Use、Map

    Run:是最后一道工序,管道末尾。

    Use:连接请求委托,next 向下走。

    Map:扩展用作约定创建管道分支。

    自定义消息返回中间件

    就是自定义消息返回值,在返回之前处理一下消息的格式和数据。(这个不建议使用,发布的时候会有fail,目前还没有时间查找,有时间了会回来解决)

    首先在Model层创建一个ErrorModel.cs 返回格式 实体类,代码如下

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace WebApi.Core.Model
    {
        /// <summary>
        /// 自定义返回消息实体类
        /// </summary>
        public class ErrorModel
        {
            /// <summary>
            /// 状态码
            /// </summary>
            public int code { get; set; } = 500;
    
            /// <summary>
            /// 错误信息
            /// </summary>
            public string msg { get; set; }
    
            /// <summary>
            /// 错误详情
            /// </summary>
            public string detail { get; set; }
    
            /// <summary>
            /// 时间戳
            /// </summary>
            public string timestamp { get; set; } = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        }
    }

    在api层增加一个文件夹Middleware 在新建一个中间件  CustomExceptionMiddleware

     代码如下,注意如果复制的话,命名空间注意一下,也可以右键-新建项-选择中间件,只需要改一下就行。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Http;
    using Newtonsoft.Json;
    using WebApi.Core.Api.Log;
    using WebApi.Core.Model;
    
    namespace WebApi.Core.Api.Middleware
    {
        // You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
        public class CustomExceptionMiddleware
        {
            private readonly RequestDelegate _next;
            private readonly ILoggerHelper _logger;
            public CustomExceptionMiddleware(RequestDelegate next, ILoggerHelper logger)
            {
                _next = next;
                _logger = logger;
            }
    
            public async Task InvokeAsync(HttpContext httpContext)
            {
                try
                {
                    await _next(httpContext);
                }
                catch (Exception ex)
                {
                    _logger.Error(ex.Message, ex); // 日志记录
                    await HandleExceptionAsync(httpContext, ex.Message);
                }
                finally
                {
                    var statusCode = httpContext.Response.StatusCode;
                    var msg = "";
                    switch (statusCode)
                    {
                        case 401:
                            msg = "未授权";
                            break;
                        case 403:
                            msg = "拒绝访问";
                            break;
                        case 404:
                            msg = "未找到服务";
                            break;
                        case 405:
                            msg = "405 Method Not Allowed";
                            break;
                        case 502:
                            msg = "请求错误";
                            break;
                    }
                    if (!string.IsNullOrWhiteSpace(msg))
                    {
                        await HandleExceptionAsync(httpContext, msg);
                    }
                }
            }
    
            private async Task HandleExceptionAsync(HttpContext httpContext, string msg)
            {
                ErrorModel error = new ErrorModel
                {
                    code = httpContext.Response.StatusCode,
                    msg = msg
                };
                var result = JsonConvert.SerializeObject(error);
                httpContext.Response.ContentType = "application/json;charset=utf-8";
                await httpContext.Response.WriteAsync(result).ConfigureAwait(false);
            }
        }
    
        // Extension method used to add the middleware to the HTTP request pipeline.
        public static class CustomExceptionMiddlewareExtensions
        {
            public static IApplicationBuilder UseCustomExceptionMiddleware(this IApplicationBuilder builder)
            {
                return builder.UseMiddleware<CustomExceptionMiddleware>();
            }
        }
    }

    注册一下中间件

    strartup.cs 中的Configure方法中 添加如下代码  顺序的话 放在权限处理(UseAuthentication)前面 就可以,不然请求从管道回来的时候会先走消息处理,然后在判断权限,这样的话就无法处理了。

     app.UseCustomExceptionMiddleware();

    接下来测试一下F5 可以看到 是没问题了。

     我们现在处理了响应消息,

    接下来我们做一个获取请求和响应的中间件

    需要保存到日志中,查看都谁访问的返回的是什么

    在middleware文件夹下创建一个中间件LogReqResponseMiddleware 代码如下

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Http;
    using WebApi.Core.Api.Log;
    
    namespace WebApi.Core.Api.Middleware
    {
        // You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
        public class LogReqResponseMiddleware
        {
            private readonly RequestDelegate _next;
            private readonly ILoggerHelper _logger;
    
            public LogReqResponseMiddleware(RequestDelegate next, ILoggerHelper logger)
            {
                _next = next;
                _logger = logger;
            }
    
            public async Task Invoke(HttpContext httpContext)
            {
                var request = httpContext.Request;
                request.EnableBuffering();
                //把请求body流转换成字符串
                string bodyAsText = await new StreamReader(request.Body).ReadToEndAsync();//记录请求信息
                var requestStr = $"{request.Scheme} {request.Host}{request.Path} {request.QueryString} {bodyAsText}";
                _logger.Info(typeof(LogReqResponseMiddleware), "Request:" + requestStr);
                request.Body.Seek(0, SeekOrigin.Begin);
    
                var originalBodyStream = httpContext.Response.Body;
                using (var responseBody = new MemoryStream())
                {
                    httpContext.Response.Body = responseBody;
                    await _next(httpContext);
    
                    var response = httpContext.Response;
                    response.Body.Seek(0, SeekOrigin.Begin);
                    //转化为字符串
                    string text = await new StreamReader(response.Body).ReadToEndAsync();
                    //从新设置偏移量0
                    response.Body.Seek(0, SeekOrigin.Begin);
    
                    //记录返回值
                    var responsestr = $"{response.StatusCode}: {text}";
                    _logger.Info(typeof(LogReqResponseMiddleware),"Response:" + responsestr);
    
                    await responseBody.CopyToAsync(originalBodyStream);
                }
            }
        }
    
        // Extension method used to add the middleware to the HTTP request pipeline.
        public static class LogReqResponseMiddlewareExtensions
        {
            public static IApplicationBuilder UseLogReqResponseMiddleware(this IApplicationBuilder builder)
            {
                return builder.UseMiddleware<LogReqResponseMiddleware>();
            }
        }
    }

    然后在startup.cs 的configure注册一下,这里位置可以随意了,因为只是记录一下并没有对请求和响应做任何事情  代码如下

     //记录请求和响应的json串
                app.UseLogReqResponseMiddleware();

    看一下效果 这里可以看到已经是记录进去了,报错是因为 我的redis没有开启。

     今天写记录到这儿吧,后期遇到业务场景后,在慢慢添加吧

  • 相关阅读:
    使用 ES2015 编写 Gulp 构建
    ES6 Promise 接口
    Git 文件比较
    JavaScript 属性描述符
    Vim 插件之 NERDTree
    Raspberry Pi 3 Model B 安装 OSMC
    How ADB works
    [Linux] zip 与 unzip 命令
    在 Ubuntu 配置 PPTP Server
    [Linux] 查看系统启动时间
  • 原文地址:https://www.cnblogs.com/xiaojinFat/p/13366836.html
Copyright © 2020-2023  润新知