You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core Web API中间件修改Request.Path未切换控制器/动作

问题原因及解决方案

你的问题出在中间件顺序错误,以及ASP.NET Core路由系统的执行时机限制导致的。

核心原因

ASP.NET Core的路由匹配(由EndpointRoutingMiddleware处理)需要在授权中间件(UseAuthorization)之前执行,但你的代码没有显式调用UseRouting,导致MapControllers隐式添加的EndpointRoutingMiddleware被放在了UseAuthorization之后。虽然你修改了Request.Path,但错误的执行顺序让路由匹配逻辑无法正确识别修改后的路径,最终还是沿用了原始路径的匹配结果。

同时,这种顺序也违反了ASP.NET Core官方推荐的中间件执行顺序,会引发授权逻辑无法正确获取端点权限配置等潜在问题。

解决方案

方案1:调整中间件顺序(推荐)

显式添加UseRouting,将自定义中间件放在UseRouting之前(确保路径修改在路由匹配前完成),同时将UseAuthorization放在UseRouting之后,符合官方规范:

using Sandbox.Middleware;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

// 自定义中间件放在UseRouting之前,保证路径修改先于路由匹配
app.UseMiddleware<ModifyControllerMiddleware>();

app.UseHttpsRedirection();

// 显式声明路由中间件,确保路由匹配在授权之前执行
app.UseRouting();

app.UseAuthorization();

app.MapControllers();

app.Run();

方案2:使用自定义路由策略(更灵活)

如果不想调整中间件顺序,可以通过实现IEndpointSelectorPolicy直接在路由匹配阶段根据请求头选择目标端点,无需修改Request.Path:

  1. 创建自定义路由策略类:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Matching;
using Microsoft.AspNetCore.Mvc.Controllers;

namespace Sandbox.Middleware
{
    public class HeaderBasedEndpointSelectorPolicy : IEndpointSelectorPolicy
    {
        public bool AppliesToEndpoints(IReadOnlyList<Endpoint> endpoints) => true;

        public Task ApplyAsync(HttpContext httpContext, CandidateSet candidates)
        {
            if (!httpContext.Request.Headers.TryGetValue("x-intercept", out var interceptValue))
                return Task.CompletedTask;

            var targetAction = interceptValue switch
            {
                "1" => "Heartbeat",
                "2" => "Deadbeat",
                _ => null
            };

            if (targetAction == null)
                return Task.CompletedTask;

            // 遍历候选端点,筛选出目标动作对应的端点
            for (int i = 0; i < candidates.Count; i++)
            {
                if (candidates[i].Endpoint.Metadata.GetMetadata<ControllerActionDescriptor>()?.ActionName == targetAction)
                {
                    // 标记该端点为有效,其余为无效
                    candidates.SetValidity(i, true);
                    for (int j = 0; j < candidates.Count; j++)
                    {
                        if (j != i) candidates.SetValidity(j, false);
                    }
                    break;
                }
            }

            return Task.CompletedTask;
        }
    }
}
  1. 在Program.cs中注册该策略:
builder.Services.AddSingleton<IEndpointSelectorPolicy, HeaderBasedEndpointSelectorPolicy>();

这种方式直接在路由匹配阶段干预端点选择,更贴合ASP.NET Core的路由设计逻辑,也避免了修改请求路径可能带来的其他副作用。

验证

调整中间件顺序或添加自定义路由策略后,发送带有x-intercept:2的请求到/Diagnostics/Heartbeat,应该会正确路由到Deadbeat动作。

内容的提问来源于stack exchange,提问作者Gabriel Read

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 06:02:01