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

如何通过_Layout页传递全局变量至所有视图?技术方案咨询

实现全局可访问的用户选择年份变量

嘿,我完全懂你的需求——就是想让用户选的年份能在所有视图里顺畅用起来,还得避开Session那种一刷新、切页面就丢数据的坑对吧?下面几个方案应该能完美解决你的问题,你可以根据项目情况挑合适的:

方案一:Cookie + 全局ActionFilter(最推荐)

这个方案把年份持久存在用户浏览器的Cookie里,同时通过全局过滤器自动把年份注入到所有视图,彻底解决数据丢失的问题:

1. 处理年份选择的存储逻辑

先写一个Action接收用户选的年份,把它存到Cookie里:

public IActionResult SetSelectedYear(int year)
{
    var cookieOptions = new CookieOptions
    {
        Expires = DateTime.Now.AddMonths(1), // 有效期设1个月,按需调整时长
        HttpOnly = false, // 允许前端读取,方便下拉列表默认选中对应年份
        SameSite = SameSiteMode.Lax
    };
    Response.Cookies.Append("UserSelectedYear", year.ToString(), cookieOptions);
    return Redirect(Request.Headers["Referer"].ToString()); // 跳回原页面,体验更流畅
}

2. 创建全局ActionFilter自动注入年份

写一个过滤器,在每个Action执行前从Cookie里读取年份,自动注入到所有视图:

public class GlobalYearFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        var httpContext = context.HttpContext;
        // 尝试从Cookie读年份,读不到就用当前年份当默认值
        if (httpContext.Request.Cookies.TryGetValue("UserSelectedYear", out var yearStr) 
            && int.TryParse(yearStr, out var selectedYear))
        {
            context.Controller.ViewBag.SelectedYear = selectedYear;
        }
        else
        {
            context.Controller.ViewBag.SelectedYear = DateTime.Now.Year;
        }
    }

    public void OnActionExecuted(ActionExecutedContext context) { }
}

3. 注册全局Filter

在Program.cs(.NET Core)里注册这个过滤器,让它对所有Action生效:

builder.Services.AddControllersWithViews(options =>
{
    options.Filters.Add<GlobalYearFilter>();
});

4. 前端使用示例

在任意视图(包括_Layout.cshtml)里直接用@ViewBag.SelectedYear,下拉列表也能默认选中用户之前选的年份:

<select onchange="window.location.href='@Url.Action("SetSelectedYear", "Home")?year='+this.value">
    @for (int y = DateTime.Now.Year - 3; y <= DateTime.Now.Year + 3; y++)
    {
        <option value="@y" @(y == ViewBag.SelectedYear ? "selected" : "")>@y</option>
    }
</select>

方案二:使用ViewComponent(适合复杂展示逻辑)

如果你的年份展示需要结合权限、额外业务数据等复杂逻辑,可以用ViewComponent来封装:

1. 创建YearSelectorViewComponent

public class YearSelectorViewComponent : ViewComponent
{
    public IViewComponentResult Invoke()
    {
        var selectedYear = DateTime.Now.Year;
        if (HttpContext.Request.Cookies.TryGetValue("UserSelectedYear", out var yearStr) 
            && int.TryParse(yearStr, out var year))
        {
            selectedYear = year;
        }
        // 返回带年份模型的视图
        return View(selectedYear);
    }
}

2. 编写ViewComponent的视图

在Views/Shared/Components/YearSelector/Default.cshtml里写下拉列表逻辑:

@model int
<select onchange="window.location.href='@Url.Action("SetSelectedYear", "Home")?year='+this.value">
    @for (int y = DateTime.Now.Year - 3; y <= DateTime.Now.Year + 3; y++)
    {
        <option value="@y" @(y == Model ? "selected" : "")>@y</option>
    }
</select>

3. 在任意视图调用

@await Component.InvokeAsync("YearSelector")

需要在其他地方获取年份的话,也可以在ViewComponent里把年份存入ViewBag,或者通过模型传递。

关于你之前的Session问题

你提到Session刷新后丢失,大概率是Session配置的问题——比如默认Session有效期只有20分钟,或者你用了无状态托管环境(比如Azure App Service)但没配置分布式缓存。不过相比Session,Cookie更适合这种用户偏好类的存储,因为它存在用户端,不依赖服务器存储,稳定性更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:27:42