.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没有开启。

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

原文地址:https://www.cnblogs.com/xiaojinFat/p/13366836.html