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

如何在.NET Core中为所有Action的URL自动追加指定查询字符串?

实现方案

问题排查

  • 你之前的过滤器方案通过重定向实现,会产生多余请求,不符合需求
  • 你之前的中间件方案失效是因为QueryString是值类型,Add()方法仅返回新实例,不会修改原请求的QueryString,必须重新赋值给context.Request.QueryString才能生效

完整实现步骤

1. 入站请求自动重写QueryString(无跳转,后台可正常读取参数)

编写自定义中间件,注意要放在Session中间件之后、路由中间件之前:

app.UseSession(); // 如果你用Session存preview值,必须先启用Session

app.Use(async (context, next) =>
{
    // 调整为你自己的preview获取逻辑,这里示例从Session取
    if (context.Session.TryGetValue("Preview", out var previewBytes) 
        && int.TryParse(System.Text.Encoding.UTF8.GetString(previewBytes), out int preview) 
        && preview > 0
        && !context.Request.Query.ContainsKey("preview"))
    {
        // 必须把Add返回的新QueryString赋值回请求
        context.Request.QueryString = context.Request.QueryString.Add("preview", preview.ToString());
    }
    await next();
});

app.UseRouting();
// 其他中间件...

2. 全局生成Action URL自动追加preview参数

该方案会对所有Url.Action()、Url.RouteUrl()、asp-action/asp-controller标签生成的链接生效,无需手动加参数:

第一步:自定义UrlHelper

public class AppendPreviewUrlHelper : UrlHelper
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    public AppendPreviewUrlHelper(ActionContext actionContext, IHttpContextAccessor httpContextAccessor) : base(actionContext)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public override string Action(UrlActionContext actionContext)
    {
        var context = _httpContextAccessor.HttpContext;
        if (context != null 
            && context.Request.Query.TryGetValue("preview", out var previewVal) 
            && !string.IsNullOrEmpty(previewVal))
        {
            actionContext.Values ??= new RouteValueDictionary();
            if (!actionContext.Values.ContainsKey("preview"))
            {
                actionContext.Values.Add("preview", previewVal);
            }
        }
        return base.Action(actionContext);
    }

    public override string RouteUrl(UrlRouteContext routeContext)
    {
        var context = _httpContextAccessor.HttpContext;
        if (context != null 
            && context.Request.Query.TryGetValue("preview", out var previewVal) 
            && !string.IsNullOrEmpty(previewVal))
        {
            routeContext.Values ??= new RouteValueDictionary();
            if (!routeContext.Values.ContainsKey("preview"))
            {
                routeContext.Values.Add("preview", previewVal);
            }
        }
        return base.RouteUrl(routeContext);
    }
}

第二步:实现自定义UrlHelper工厂

public class AppendPreviewUrlHelperFactory : IUrlHelperFactory
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    public AppendPreviewUrlHelperFactory(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public IUrlHelper GetUrlHelper(ActionContext context)
    {
        return new AppendPreviewUrlHelper(context, _httpContextAccessor);
    }
}

第三步:注册服务

在Program.cs(.NET 6+)或者Startup.cs的ConfigureServices方法中注册:

// 注册HttpContextAccessor
builder.Services.AddHttpContextAccessor();
// 替换默认的UrlHelper工厂
builder.Services.AddSingleton<IUrlHelperFactory, AppendPreviewUrlHelperFactory>();
// 注册Session(如果用Session存preview)
builder.Services.AddSession(opt =>
{
    opt.Cookie.HttpOnly = true;
    opt.IdleTimeout = TimeSpan.FromMinutes(30);
});

// 如果需要自动把请求里的preview存到Session,注册全局过滤器
builder.Services.AddControllersWithViews(opt =>
{
    opt.Filters.Add<SavePreviewFilter>();
});

可选:新增自动存preview的全局过滤器

public class SavePreviewFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        if (context.HttpContext.Request.Query.TryGetValue("preview", out var previewVal) 
            && int.TryParse(previewVal, out int preview))
        {
            context.HttpContext.Session.SetInt32("Preview", preview);
        }
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 14:45:05