.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沒有開啟。

 

 今天寫記錄到這兒吧,后期遇到業務場景后,在慢慢添加吧


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM