Asp.Net Core 中间件应用实践中你不知道的那些事

一、概述

这篇文章主要分享Endpoint 终结点路由的中间件的应用场景及实践案例,不讲述其工作原理,如果需要了解工作原理的同学,
可以点击查看以下两篇解读文章:

1.1 中间件(Middleware)的作用

我们知道,任何的一个web框架都是把http请求封装成一个管道,每一次的请求都是经过管道的一系列操作,最终到达我们写的代码中。那么中间件就是在应用程序管道中的一个组件,用来拦截请求过程进行一些其他处理和响应。中间件可以有很多个,每一个中间件都可以对管道中的请求进行拦截,它可以决定是否将请求转移给下一个中间件。

asp.net core 提供了IApplicationBuilder接口来让把中间件注册到asp.net的管道请求当中去,中间件是一个典型的AOP应用。 下面是一个微软官方的一个中间件管道请求图:

1.2 中间件和过滤器的区别

Filter是延续ASP.NET MVC的产物,同样保留了五种的Filter,分别是Authorization Filter、Resource Filter、Action Filter、Exception Filter及Result Filter。
具体可以查看我上次分享的一篇Asp.Net Core Filter 深入浅出的那些事-AOP 的文章.

根据描述,可以看出中间件和过滤器的功能类似,那么他们有什么区别?为什么又要搞一个中间件呢?
其实,过滤器和中间件他们的关注点是不一样的,也就是说职责不一样,干的事情就不一样。

同作为两个AOP利器,Filter(过滤器)更贴合业务,它关注于应用程序本身,比如你看ActionFilterResultFilter,它都直接和你的ActionActionResult交互了,是不是离你很近的感觉,那我有一些比如对我的输出结果进行格式化,对我的请求的ViewModel进行数据验证啦,肯定就是用Filter无疑了。它是MVC的一部分,它可以拦截到你Action上下文的一些信息,而中间件是没有这个能力的。

可以看到,每一个中间件都都可以在请求之前和之后进行操作。请求处理完成之后传递给下一个请求

1.3 中间件的使用场景

那么,何时使用中间件呢?我的理解是在我们的应用程序当中和业务关系不大的一些需要在管道中做的事情可以使用,比如身份验证,Session存储,日志记录等。其实我们的 Asp.net core项目中本身已经包含了很多个中间件。比如 身份认证中间件 UseAuthorization()等系列.

二、中间件实战

需求场景:通过后端记录每一次的访问请求日志,同时需要根据需要排除一些Controller 或者Action 不记录请求的日志信息。

思考:经过分析我需要创建一个全局的中间件进行拦截路由,并且写入日志;同时需要添加一个特性Attribute 进行标注那些Controller或者Action 不需要进行日志记录。

我们来创建LogsMiddleware 中间件代码,代码如下:

public class LogsMiddleware
{
        private readonly RequestDelegate _next;

        public LogsMiddleware(RequestDelegate next)
        {
            this._next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            var endpoint = context.Features.Get<IEndpointFeature>()?.Endpoint;
            if (endpoint == null)
            {
                await _next(context);
                return;
            }

            using (var scope = context.RequestServices.CreateScope())
            {
                var _logger = scope.ServiceProvider.GetService<ILogger<LogsMiddleware>>();

                var attruibutes = endpoint.Metadata.OfType<NoLogsAttriteFilter>();
                if (attruibutes.Count()==0)
                {
                    _logger.LogInformation($" url:{context.Request.Path}, 访问时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
                }

                //记录 排除的特殊Message 信息
                foreach (var attribute in attruibutes)
                {
                    _logger.LogInformation(attribute.Message);
                }
            }
            await _next(context);
        }
}

NoLogsAttriteFilter 过滤器代码如下:

public class NoLogsAttriteFilter : Attribute
{
        /// <summary>
        /// 这里加这个主要是把获取到的信息在中间件中打印出来,区分中间件的拦截用处
        /// </summary>
        public string Message = "";

        public NoLogsAttriteFilter(string message)
        {
            Message = message;
        }
}

Startup 中的代码如下:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseRouting();
            app.UseAuthorization();
            app.UseMiddleware<LogsMiddleware>();//添加日志记录中间件
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
}

HomeController 控制器中的两个Action 代码如下::

// 访问该路由会记录访问日志
public IActionResult Index()
{
        return View();
}

//访问该路由不会记录访问日志
[NoLogsAttriteFilter("Manage 不需要记录访问日志")]
public IActionResult Manage()
{
       return View();
}

这样就自定义日志中间件就已经完成了我上面的需求,不依赖于任何业务独立存在于系统中;从代码中我们可以看到中间件通过context.Features.Get<IEndpointFeature>()?.Endpoint; 方法获得终结点路由方式进行匹配,并且可以通过endpoint.Metadata.OfType<NoLogsAttriteFilter>() 方式获得Action 中的特性信息数据,并通过该拦截进行我的需求
自定义中间件教程文章请点击自定义中间件官方教程 一文。

现在我们再来印证下我上一篇关于 Asp.Net Core EndPoint 终结点路由工作原理解读 一文 中提及到UseRouting() 中间件是遍历所有的Endpoint 终结点路由以匹配当前请求的 Endpoint 终结点路由一说,我把注册LogsMiddleware中间件和UseRouting() 路由中间件代码顺序调整一下,代码如下:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

// 中间件注册放到了UseRouting() 之前
            app.UseMiddleware<LogsMiddleware>();//添加日志记录中间件

            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
}

再来看看运行调试的结果如图:

从调试的结果图中可以看出 endpoint 变量是 null;所有需要使用到Endpoint 终结点路由必须注册在UseRouting() 中间件之后。

三、官方常用中间件

  1. 异常/错误处理
    当应用在开发环境中运行时:
    开发人员异常页中间件 (UseDeveloperExceptionPage) 报告应用运行时错误。
    数据库错误页中间件报告数据库运行时错误。
    当应用在生产环境中运行时:
    异常处理程序中间件 (UseExceptionHandler) 捕获以下中间件中引发的异常。
    HTTP 严格传输安全协议 (HSTS) 中间件 (UseHsts) 添加 Strict-Transport-Security 标头。
  2. HTTPS 重定向中间件 (UseHttpsRedirection) 将 HTTP 请求重定向到 HTTPS。
  3. 静态文件中间件 (UseStaticFiles) 返回静态文件,并简化进一步请求处理。
  4. Cookie 策略中间件 (UseCookiePolicy) 使应用符合欧盟一般数据保护条例 (GDPR) 规定。
  5. 用于路由请求的路由中间件 (UseRouting)。
  6. 身份验证中间件 (UseAuthentication) 尝试对用户进行身份验证,然后才会允许用户访问安全资源。
  7. 用于授权用户访问安全资源的授权中间件 (UseAuthorization)。
  8. 会话中间件 (UseSession) 建立和维护会话状态。 如果应用使用会话状态,请在 Cookie 策略中间件之后和 MVC 中间件之前调用会话中间件。
  9. 用于将 Razor Pages 终结点添加到请求管道的终结点路由中间件(带有 MapRazorPages 的 UseEndpoints)。

以上如果有错误的地方,请大家积极纠正,谢谢大家的支持!!

(0)

相关推荐

  • ASP.NET Core笔记(5) - 中间件

    中间件管道模型 中间件的配置 自定义中间件 中间件是一类装配在应用管道的代码,负责处理请求和响应.每个中间件都可在管道中的下一个组件前后执行工作,并选择是否将请求传递到管道中的下一个中间件.在Star ...

  • ASP.NET Core 中间件详解及项目实战

    WEB前端开发社区 昨天 前言 本篇文章是我们在开发自己的项目中实际使用的,比较贴合实际应用,算是对中间件的一个深入使用了,不是简单的Hello World,如果你觉得本篇文章对你有用的话,不妨点个[ ...

  • ASP.NET CORE 管道模型及中间件使用解读

    说到ASP.NET CORE 管道模型不得不先来看看之前的ASP.NET 的管道模型,两者差异很大,.NET CORE 3.1 后完全重新设计了框架的底层,.net core 3.1 的管道模型更加灵 ...

  • .NET Core技术研究-中间件的由来和使用

    今天 前言 我们将原有ASP.NET应用升级到ASP.NET Core的过程中,会遇到一个新的概念:中间件. 中间件是ASP.NET Core全新引入的概念.中间件是一种装配到应用管道中以处理请求和响 ...

  • Asp.Net Core安全防护-客户端IP白名单限制

    前言 本篇展示了如何在ASP.NET Core应用程序中设置IP白名单验证的2种方式. 你可以使用以下2种方式: 用于检查每个请求的远程 IP 地址的中间件. MVC 操作筛选器,用于检查针对特定控制 ...

  • 一文说通Dotnet Core的中间件

    前几天,公众号后台有朋友在问Core的中间件,所以专门抽时间整理了这样一篇文章. 一.前言 中间件(Middleware)最初是一个机械上的概念,说的是两个不同的运动结构中间的连接件.后来这个概念延伸 ...

  • Dotnet Core异常处理的优雅实践

    异常处理,也可以做得很优雅. 一.前言 异常处理的重要性,老司机都清楚. 这篇文章,我们来理一下Dotnet Core异常处理的几种方式. Try Catch方式 Exception Filter方式 ...

  • 14.ASP.NET Core请求处理管道

    在这篇文章中,我将通过一个示例,来讲解ASP.NET Core中的请求处理管道.在这篇文章中,我们将讨论下面几个点: 理解ASP.NET Core请求处理管道 怎样在ASP.NET中创建并注册多个中间 ...

  • 基于ASP.NET core的MVC站点开发笔记 0x01

    我的环境 OS type:macSoftware:vscodeDotnet core version:2.0/3.1 dotnet sdk下载地址:https://dotnet.microsoft.c ...

  • asp.net core 3.x 授权中的概念

    前言 预计是通过三篇来将清楚asp.net core 3.x中的授权:1.基本概念介绍:2.asp.net core 3.x中授权的默认流程:3.扩展. 在完全没有概念的情况下无论是看官方文档还是源码 ...

  • ASP.Net Core 5.0 MVC中AOP思想的体现(五种过滤器)并结合项目案例说明过滤器的用法

    执行顺序 使用方法,首先实现各自的接口,override里面的方法, 然后在startup 类的 ConfigureServices 方法,注册它们. services.AddTransient(ty ...

  • 《聊斋志异》中你不知道的那些事—“瞳人语”

    "写鬼写妖高人一等,刺贪刺虐入骨三分". 郭沫若先生的两句话,将<聊斋志异>的精髓体现得淋漓尽致.今天开始,由我来带你走进<聊斋>的世界. 聊斋志异 长安有 ...

  • 先天八卦和后天八卦的作用及其在风水实践中的断事方法

    上图为"伏羲八卦",也叫"先天八卦": 一是周文王的"乾坤学说":他认为先有天地,天地相交而生成万物,天即乾为父,地即坤为母,八卦其余六卦皆 ...

  • 13.在ASP.NET Core中配置中间件组件

    这篇文章中,我们将一起学习在ASP.NET Core中配置中间件组件,以便处理请求处理管道.在阅读这篇文章之前,麻烦大家先去看看,我前面写的一篇文章:ASP.NET Core中间件组件.在这篇文章中, ...

  • 如何解决在ASP.NET Core中找不到图像时设置默认图像

    dotNET跨平台 今天 以下文章来源于UP技术控 ,作者conan5566 UP技术控不止IT 还有生活 背景 web上如果图片不存在一般是打xx,这时候一般都是会设置默认的图片代替.现在用中间件的 ...

  • .NET 6 Preview 3 中 ASP.NET Core 的更新和改进

    原文:bit.ly/2Qb56NP作者:Daniel Roth译者:精致码农-王亮.NET 6 预览版 3 现已推出,其中包括许多对新的 ASP.NET Core 改进.以下是本次预览版的新内容:更小 ...

  • 一图看懂 ASP.NET Core 中的服务生命周期

    dotNET跨平台 今天 以下文章来源于技术译站 ,作者技术译民 翻译自 Waqas Anwar 2020年11月8日的文章 <ASP.NET Core Service Lifetimes (I ...