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

基于HttpContext.SetEndpoint的.NET Core请求重写中间件实现问题

.NET Core 中间件重写请求路径到指定Action的正确实现

为什么修改路径后没生效?

ASP.NET Core的路由匹配是在UseRouting中间件阶段完成的,如果在路由匹配之后修改Request.Path,不会触发重新路由。另外SetEndpoint是直接指定已匹配的端点,而非修改路径,需要用正确的方式结合使用。

方法一:修改请求路径并触发重新路由

通过修改Request.Path并清除已有路由数据,让路由中间件重新匹配目标Action。

代码示例

// 自定义重写中间件,必须放在UseRouting之前
app.Use(async (context, next) =>
{
    // 匹配需要重写的原始路径
    if (context.Request.Path.Equals("/old-path", StringComparison.OrdinalIgnoreCase))
    {
        // 重写为目标Action的路径
        context.Request.Path = "/Home/TargetAction";
        // 清除路由数据,强制路由中间件重新匹配
        var routingFeature = context.Features.Get<IRoutingFeature>();
        if (routingFeature?.RouteData != null)
        {
            routingFeature.RouteData.Values.Clear();
        }
    }
    await next();
});

// 路由中间件,必须在重写中间件之后
app.UseRouting();

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

方法二:直接用SetEndpoint指定目标Action

通过获取目标Action的描述符,直接创建并设置Endpoint,跳过路由匹配流程。

代码示例

  1. 先确保注入Action描述符服务(Program.cs中):
builder.Services.AddSingleton<IActionDescriptorCollectionProvider, ActionDescriptorCollectionProvider>();
  1. 自定义中间件:
app.Use(async (context, next) =>
{
    if (context.Request.Path.Equals("/old-path", StringComparison.OrdinalIgnoreCase))
    {
        var actionProvider = context.RequestServices.GetRequiredService<IActionDescriptorCollectionProvider>();
        // 定位目标Action(替换为你的控制器和Action名称)
        var targetAction = actionProvider.ActionDescriptors.Items
            .OfType<ControllerActionDescriptor>()
            .FirstOrDefault(ad => 
                ad.ControllerName.Equals("Home", StringComparison.OrdinalIgnoreCase) && 
                ad.ActionName.Equals("TargetAction", StringComparison.OrdinalIgnoreCase));

        if (targetAction != null)
        {
            // 创建Endpoint实例
            var endpoint = new Endpoint(
                _ => Task.CompletedTask,
                new EndpointMetadataCollection(targetAction),
                targetAction.DisplayName);
            
            // 设置Endpoint,后续流程将直接使用这个端点
            context.SetEndpoint(endpoint);
            
            // 如需传递路由参数,可设置RouteData
            var routingFeature = context.Features.Get<IRoutingFeature>() ?? new RoutingFeature();
            routingFeature.RouteData.Values["id"] = "123"; // 示例参数
            context.Features.Set(routingFeature);
        }
    }
    await next();
});

app.UseRouting();

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

关键注意事项

  • 中间件顺序:重写逻辑必须放在UseRouting之前,否则路由已完成匹配,修改不会生效。
  • SetEndpoint需要确保目标Action存在,否则会返回404。
  • 传递参数时,需同步更新RouteData的值,保证Action能正确接收参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 19:10:38