ASP.NET Core 中间件

news2024/9/20 22:05:28

一、什么是中间件?

  • 中间件 是一种装配到 ASP.NET Core 应用程序请求处理管道中的软件组件,用于处理 HTTP 请求和响应。
    在这里插入图片描述

  • 每个中间件组件可以:

    • 选择是否将请求传递到下一个中间件:通过调用 next() 或者不调用 next() 来决定是否将请求继续传递给下一个中间件。

    • 在传递前后执行某些操作:可以在将请求传递给下一个中间件之前或者之后执行一些自定义逻辑。

    • 请求委托用于生成请求管道。 请求委托处理每个 HTTP 请求。

  • 中间件的作用:中间件比筛选器更底层和更上游,是一种性能更高、适用范围更广的面向切面技术,可处理如网关、URL 转发、限流等复杂操作。
    在这里插入图片描述

二、常见的中间件

1. 所有请求返回同一个结果

  • 这个中间件会对所有请求返回相同的响应内容,不论请求的 URL 是什么。
app.Run(async context =>
{
    await context.Response.WriteAsync("Hello world!");  // 所有请求的响应内容
});

2. 拦截所有请求

  • 通过 app.Use 方法可以拦截所有请求,并在处理请求时进行一些操作,例如设置统一的 HTTP 头信息。
app.Use(async (context, next) =>
{
    context.Response.Headers["framework"] = "Furion";  // 设置自定义响应头
    await next.Invoke();  // 将请求传递给下一个中间件
});

3. 特定路由中间件

  • 这个中间件仅对特定的 URL 路径进行处理,例如 /hello
app.Map("/hello", app => {
    app.Run(async context =>
    {
        await context.Response.WriteAsync("Map Test 1");  // 仅对 /hello 路径进行处理
    });
});

4. 嵌套路由中间件

  • 中间件可以嵌套使用,根据不同的路由层级进行处理,例如处理 /level1/level2a/level1/level2b 路径的请求。
app.Map("/level1", level1App => {
    level1App.Map("/level2a", level2AApp => {
        level2AApp.Run(async context =>
        {
            await context.Response.WriteAsync("Map Level 2A");
        });
    });
    level1App.Map("/level2b", level2BApp => {
        level2BApp.Run(async context =>
        {
            await context.Response.WriteAsync("Map Level 2B");
        });
    });
});

三、自定义中间件

1. 通过 app.Use 定义中间件

  • 这是定义中间件的最简单方式,但通常不推荐用于复杂场景。可以直接在 app.Use 内部编写中间件逻辑。
app.Use(async (context, next) =>
{
    var cultureQuery = context.Request.Query["culture"];  // 获取请求中的 culture 查询参数
    if (!string.IsNullOrWhiteSpace(cultureQuery))
    {
        var culture = new CultureInfo(cultureQuery);
        CultureInfo.CurrentCulture = culture;  // 设置当前文化信息
        CultureInfo.CurrentUICulture = culture;  // 设置当前 UI 文化信息
    }
    await next(context);  // 将请求传递给下一个中间件
});

2. 通过独立类定义中间件(推荐)

  • 创建一个独立的中间件类,并通过 app.UseMiddleware 方法来使用这个中间件。这种方式便于复用和维护。
public class RequestCultureMiddleware
{
    private readonly RequestDelegate _next;

    public RequestCultureMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var cultureQuery = context.Request.Query["culture"];  // 从查询字符串中获取文化信息
        if (!string.IsNullOrWhiteSpace(cultureQuery))
        {
            var culture = new CultureInfo(cultureQuery);
            CultureInfo.CurrentCulture = culture;  // 设置当前线程的文化信息
            CultureInfo.CurrentUICulture = culture;  // 设置当前线程的 UI 文化信息
        }
        await _next(context);  // 将请求传递给下一个中间件
    }
}

// 扩展方法
public static class RequestCultureMiddlewareExtensions
{
    public static IApplicationBuilder UseRequestCulture(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<RequestCultureMiddleware>();  // 使用自定义中间件
    }
}

// 使用中间件
app.UseRequestCulture();

3. 配置更多参数

  • 中间件可以接收更多的构造参数,包括依赖注入的服务和普通参数。
public class RequestCultureMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<RequestCultureMiddleware> _logger;

    public RequestCultureMiddleware(RequestDelegate next, ILogger<RequestCultureMiddleware> logger, int age, string name)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        _logger.LogInformation("Executing middleware for {Name} who is {Age} years old.", name, age);  // 使用日志记录操作信息
        await _next(context);  // 继续执行下一个中间件
    }
}

// 扩展方法
public static class RequestCultureMiddlewareExtensions
{
    public static IApplicationBuilder UseRequestCulture(this IApplicationBuilder builder, int age, string name)
    {
        return builder.UseMiddleware<RequestCultureMiddleware>(new object[] { age, name });  // 传递参数到中间件
    }
}

// 使用中间件
app.UseRequestCulture(30, "百小僧");

四、中间件的顺序

  • 中间件的执行顺序 是至关重要的,它决定了每个中间件在请求处理管道中的位置。中间件按照它们在代码中注册的顺序依次执行,先注册的中间件先执行,后注册的中间件后执行。因此,顺序的安排会直接影响到应用的行为。

五、依赖注入/解析服务

  • 中间件可以通过构造函数注入服务,也可以在中间件内部通过 HttpContext.RequestServices 解析服务。这样可以在中间件中使用已经注册的服务。
public class RequestCultureMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<RequestCultureMiddleware> _logger;

    public RequestCultureMiddleware(RequestDelegate next, ILogger<RequestCultureMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var repository = context.RequestServices.GetService<IRepository>();  // 解析服务
        await _next(context);  // 继续执行下一个中间件
    }
}

六、删除特定的 HTTP 响应头

  • 可以通过中间件删除或修改 HTTP 响应头。例如,删除默认添加的响应头信息。
app.Use(async (context, next) =>
{
    context.Response.Headers.Remove("Server");  // 删除 Server 响应头
    await next();  // 继续执行下一个中间件
});

七、常见问题

  • 在中间件中获取终点路由的特性或其他信息时,可以通过以下方式实现:
var endpointFeature = context.Features.Get<IEndpointFeature>();  // 获取终点特性
var attribute = endpointFeature?.Endpoint?.Metadata?.GetMetadata<YourAttribute>();  // 获取自定义的特性
  • 需要注意的是,这种操作必须在 UseRouting()UseEndpoints() 之间的中间件中调用,才能确保路由信息已经解析。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2118043.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HTML5中的数据存储sessionStorage、localStorage

第8章 HTML5中的数据存储 之前通常使用Cookie存储机制将数据保存在用户的客户端。 H5增加了两种全新的数据存储方式&#xff1a;Web Stroage和Web SQL Database. 前者用于临时或永久保存客户端少量数据&#xff0c;后者是客户端本地化的一套数据库系统。 8.1 Web Storage存…

日本“大米荒”持续!政府再次拒绝投放储备米

KlipC报道&#xff1a;日本多地从7月开始出现“大米荒”&#xff0c;有部分新米上市&#xff0c;但是许多超市的大米仍然存在断购或限购的情况&#xff0c;并且部分新米价格上涨至去年同期的两倍。大阪府官员再次呼吁日本中央政府尽快投放储备米以缓解供应紧张&#xff0c;但遭…

Dynamics CRM Ribbon Workbench-the solution contains non-entity components

今天在一个低版本的环境里准备用Ribbon Workbench去编辑一个按钮时&#xff0c;遇到了如下错误 一开始没当回事&#xff0c;以为是我的解决方案问题&#xff0c;去检查了下&#xff0c;只有一个组件&#xff0c;并且哪怕我把组件换成了某个实体也不行&#xff0c;尝试了其他任何…

开源NAS系统-OpenMediaVault(OMV)共享存储网盘搭建和使用(保姆级教程)

1、OpenMediaVault简介 OpenMediaVault,简称:OMV,是由原 FreeNAS 核心开发成员 Volker Theile 发起的基于 Debian Linux 的开源 NAS 操作系统,主要面向家庭用户和小型办公环境。 OpenMediaVault是一款基于Debian Linux的开源网络附加存储(NAS)操作系统,它提供了强大的存…

酒店智能轻触开关:智慧化的创新实践

在追求高品质住宿体验的今天&#xff0c;酒店智能轻触开关作为智慧酒店建设的关键一环&#xff0c;正逐步成为提升酒店服务品质、优化运营效率、增强顾客满意度的有力工具。本文将深入探讨酒店智能轻触开关如何助力酒店实现智慧化管理&#xff0c;以及它所带来的多重变革。 一、…

大模型时代下,nlp初学者需要怎么入门?

前言 自从 ChatGPT 横空出世以来&#xff0c;自然语言处理&#xff08;Natural Language Processing&#xff0c;NLP&#xff09;研究领域就出现了一种消极的声音&#xff0c;认为大模型技术导致 NLP “死了”。 有人认为 NLP 的市场肯定有&#xff0c;但 NLP 的研究会遇到麻…

图片产生3D模型

HyperHuman 上传图片&#xff0c;点击生成 可以多生成几次&#xff0c;点击应用 让效果再好一点 生成完成之后可以导出为fbx格式

实战|等保2.0 Oracle数据库测评过程

以下等保测评过程以Oracle 11g为例&#xff0c;通过PL/SQL进行管理&#xff0c;未进行任何配置、按照等保2.0标准&#xff0c;2021报告模板&#xff0c;三级系统要求进行测评。 一、身份鉴别 a) 应对登录的用户进行身份标识和鉴别&#xff0c;身份标识具有唯一性&#xff0c;…

E212: Can‘t open file for writing

如图 1. 查看当前用户的用户名和所属组 如果你只想查看当前登录用户的用户名和所属组&#xff0c;可以使用以下命令&#xff1a; whoami groups 检查文件和目录权限&#xff1a; ls -ld /private/var/log/wyhy ls -l /private/var/log/wyhy/market.log 修改文件权限&#…

RAKsmart美国大带宽服务器租用体验怎么样?

RAKsmart是一家提供全球服务器租用服务的知名供应商&#xff0c;其在美国的服务器产品种类多样&#xff0c;包括大带宽服务器、多IP站群服务器以及高防御服务器等&#xff0c;以适应不同业务的需求。rak小编为您整理发布。 下面是对RAKsmart美国大带宽服务器租用的具体介绍&…

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

随机分类,保持均衡水平Python

1、目的&#xff1a; 10000个样本有4个指标&#xff0c;按照逾期金额分10类&#xff0c;确保每类别逾期金额均衡。 2、数据&#xff1a; 3、思路&#xff1a; 将10000个样本按照逾期金额排序&#xff0c; 等距分箱为2500个类别 增加一列随机数 根据类别和随机数升序排列 增加…

MCU6.用keil新建项目

1.新建项目 打开keil4 2.选择单片机的类型 STC并没有出现在其中,但兼容8051芯片,选Atmel的AT89C51或AT89C52均可 本文选AT89C52 弹出的窗口点否 3.查看项目 4.新建文件 5.保存文件 6.将文件添加到工程 双击Source Group 1 点击Add 7.添加已有的工程 如果要添加已有的工程 8…

Java并发编程实战 09 | 为什么需要

什么是守护线程&#xff1f; 守护线程&#xff08;Daemon Thread&#xff09;是Java中的一种特殊线程&#xff0c;那么相对于普通线程它有什么特别之处呢&#xff1f; 在了解守护线程之前&#xff0c;我们先来思考一个问题&#xff1a;JVM在什么情况下会正常退出&#xff1f;…

腾讯公众号种类这么多,为什么小程序能脱颖而出

在微信公众平台中&#xff0c;公众号和小程序是两种不同的功能实体&#xff0c;它们各自承担着不同的角色和使命。然而&#xff0c;随着小程序的崛起&#xff0c;它在众多功能中逐渐脱颖而出&#xff0c;成为商家和开发者的新宠。具体分析如下&#xff1a; 技术优势与用户体验 …

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤&#xff08;UserCF&#xff09;2. 基于物品的协同过滤&#xff08;ItemCF&#xff09;3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过…

顶点照明渲染路径

1. 顶点照明渲染路径处理光照的方式 基本思想就是所有的光都按照逐顶点的方式进行计算的&#xff0c;在内置渲染管线中&#xff0c;它只会最多记录8个光源的数据&#xff0c;只会将光相关的数据填充到那些逐顶点相关的内置光源变量 顶点照明渲染路径仅仅是前向渲染路径的一个…

Mybatis-PlusDruid数据源

一、Mybatis-Plus简介 &#xff08;一&#xff09;什么是Mybatis-Plus Mybatis-Plus是一个Mybatis&#xff08;OPENS NEW WINDOW&#xff09;的增强工具&#xff0c;在Mybatis的基础上只做增强不做改变&#xff0c;为简化开发。 &#xff08;二&#xff09;Mybatis-Plus的优…

C语言之头文件,预处理命令#include

0 为什么要添加头文件&#xff1f;为什么要使用头文件&#xff1f; 可以看下下面图片左边&#xff0c;是不使用头文件&#xff0c;假设我们为了实现某些功能&#xff0c;编写的函数&#xff0c;全部声明在主函数之前&#xff0c;写几个函数还行&#xff0c;如果是大型项目&…

Hadoop压缩技术与Hive文件格式详解

目录 文件格式和压缩 Hadoop压缩概述 压缩格式 Hive文件格式 Text File ORC 1&#xff09;文件格式 2&#xff09;结构 3&#xff09;建表语句 Parquet 1&#xff09;文件格式 2&#xff09;结构 3&#xff09;建表语句 压缩 Hive表数据进行压缩 1&#xff09;TextFil…