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)。

如果您觉的不错,请微信扫码关注 【dotNET博士】公众号,后续给您带来更精彩的分享

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

原文地址:https://www.cnblogs.com/jlion/p/12430522.html

时间: 2024-10-13 10:39:40

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

Asp.net core 中间件简单应用

Asp.net core中间件 ,处理http请求和响应的中间组件,对比起asp.net ,asp.net core 管道机制,可以说是帅气十足,简单直接.下面是通过中间件对一个请求的url 指定路由 新建webapi 项目 Startup类中Configure方法中添加处理中间件代码如下 public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app

ASP.NET Core中间件(Middleware)实现WCF SOAP服务端解析

ASP.NET Core中间件(Middleware)进阶学习实现SOAP 解析. 本篇将介绍实现ASP.NET Core SOAP服务端解析,而不是ASP.NET Core整个WCF host. 因为WCF中不仅仅只是有SOAP, 它还包含很多如消息安全性,生成WSDL,双工信道,非HTTP传输等. ASP.NET Core 官方推荐大家使用RESTful Web API的解决方案提供网络服务. SOAP 即 Simple Object AccessProtocol 也就是简单对象访问协议.

ASP.NETCore学习记录(二) —— ASP.NET Core 中间件

ASP.NET Core 中间件 目录: IApplicationBuilder 什么是中间件 ? 使用 IApplicationBuilder 创建中间件 Run.Map 与 Use 方法 实战中间件 参考原文 我们知道在 ASP.NET 中,有一个面向切面的请求管道,由22个主要的事件构成,能够让我们在往预定的执行顺序里面添加自己的处理逻辑.一般采取两种方式:一种是直接在 Global.asax 中对应的方法中直接添加代码.一种是是在 web.config 中通过注册 HttpModule

基于Jenkins Pipeline的ASP.NET Core持续集成实践

原文:基于Jenkins Pipeline的ASP.NET Core持续集成实践 最近在公司实践持续集成,使用到了Jenkins的Pipeline来提高团队基于ASP.NET Core API服务的集成与部署,因此这里总结一下. 一.关于持续集成与Jenkins Pipeline 1.1 持续集成相关概念 互联网软件的开发和发布,已经形成了一套标准流程,最重要的组成部分就是持续集成(Continuous integration,简称 CI) . 持续集成指的是,频繁地 (一天多次) 将代码集成到

ASP.NET Core 中间件基本用法

ASP.NET Core 中间件 ASP.NET Core的处理流程是一个管道,而中间件是装配到管道中的用于处理请求和响应的组件.中间件按照装配的先后顺序执行,并决定是否进入下一个组件.中间件管道的处理流程如下图(图片来源于官网): 管道式的处理方式,更加方便我们对程序进行扩展. 使用中间件 ASP.NET Core中间件模型是我们能够快捷的开发自己的中间件,完成对应用的扩展,我们先从一个简单的例子了解一下中间件的开发. Run 首先,我们创建一个ASP.NET Core 应用,在Startup

12.ASP.NET Core 中间件组件

这篇文章中,我将带领大家一起详细学习:ASP.NET Core Middleware Components.这篇文章中,我将详细讨论下面几个问题: 什么是ASP.NET Core 中的中间件组件? ASP.NET Core应用程序中,在哪里来使用中间件组件? 怎样来配置ASP.NET Core 应用程序中的中间件组件? 使用中间件组件的例子有哪些? ASP.NET Core应用程序中,中间件组件执行的顺序是? 什么是ASP.NET Core中间件组件? ASP.NET Core中间件组件就是组装

ASP.NET Core - 中间件与管道(1)

今天来讨论一个ASP.NET Core 很重要概念管道和中间件,在ASP.NET Core中,针对HTTP请求采用pipeline也就是通常说的管道方式来处理,而管道容器内可以挂载很多中间件(处理逻辑)“串联”来处理HTTP请求,每一个中间件都有权决定是否需要执行下一个中间件,或者直接做出响应.这样的机制使得HTTP请求能够很好的被层层处理和控制,并且层次清晰处理起来甚是方便. 示意图如下: 为了再次说明管道和中间件的概念,举一个官方给出的权限验证的例子,中间件A,B分别按顺序挂载在管道容器中,

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

前言 在上篇文章主要介绍了DotNetCore项目状况,本篇文章是我们在开发自己的项目中实际使用的,比较贴合实际应用,算是对中间件的一个深入使用了,不是简单的Hello World,如果你觉得本篇文章对你有用的话,不妨点个[推荐]. 目录 中间件(Middleware)的作用 中间件的运行方式 中间件(Middleware)和过滤器(Filter)的区别 什么情况我们需要中间件 怎么样自定义自己的中间件 中间件(Middleware)的作用 我们知道,任何的一个web框架都是把http请求封装成

ASP.NET Core MVC TagHelper实践HighchartsNET快速图表控件-开源

ASP.NET Core MVC TagHelper最佳实践HighchartsNET快速图表控件支持ASP.NET Core. 曾经在WebForms上写过 HighchartsNET快速图表控件-开源 Highcharts的ASP.NET Web自定义控件. 今天我就来改造它,将其使用最新的TagHelper 来实践,学习TagHelper 的使用也提供一个方便的图表控件在ASP.NET Core MVC中使用. 下面正式开始,使用之前的代码直接进行迁移升级. GitHub:https://