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

.NET Core MVC:存储当前子用户ID及默认跳转的最佳实践

问题1:存储当前查看子用户ID的最佳方案

先明确各方案的局限性:

  • ViewBag:仅作用于当前请求周期,刷新即失效,完全不适合长期存储状态
  • TempData:默认基于Session,仅保留到下一次请求(需手动调用Keep()才会延长),不符合"直至主动切换"的持久需求
  • Cookie/Session:是更合适的选择——Cookie适合客户端持久存储,Session则在服务器端存数据(仅客户端保留SessionId),安全性更高

Cookie实现示例(适合非敏感场景)

设置当前子用户ID

在切换子用户的Action中:

public IActionResult SwitchChild(string childId)
{
    // 先校验该子用户是否属于当前家长(省略权限逻辑)
    Response.Cookies.Append(
        "CurrentChildId", 
        childId, 
        new CookieOptions
        {
            Expires = DateTimeOffset.Now.AddDays(7),
            HttpOnly = true, // 禁止前端JS读取,降低XSS风险
            Secure = true, // 生产环境启用,仅HTTPS传输
            SameSite = SameSiteMode.Strict
        });
    return RedirectToAction("ChildDashboard");
}

读取当前子用户ID

// Controller中读取
var currentChildId = Request.Cookies["CurrentChildId"];

// 视图中读取
@{ var currentChildId = Context.Request.Cookies["CurrentChildId"]; }

Session实现示例(适合敏感场景)

首先在Program.cs中启用Session:

builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromHours(2);
    options.Cookie.HttpOnly = true;
    options.Cookie.Secure = true;
});

app.UseSession(); // 需放在UseRouting之后、UseAuthorization之前

设置Session

public IActionResult SwitchChild(string childId)
{
    // 权限校验
    HttpContext.Session.SetString("CurrentChildId", childId);
    return RedirectToAction("ChildDashboard");
}

读取Session

var currentChildId = HttpContext.Session.GetString("CurrentChildId");

问题2:首个子用户ID的存储与默认跳转策略

核心逻辑:家长登录后,自动查询其名下子用户,若存在则选中第一个并存储状态,跳转至对应视图;若无子用户则引导创建。

登录时直接处理的示例

public async Task<IActionResult> Login(string returnUrl = null)
{
    // 完成登录逻辑(省略)
    var parentId = User.FindFirstValue(ClaimTypes.NameIdentifier);
    
    // 查询当前家长的所有子用户(假设存在ParentChild关联表)
    var children = await _dbContext.ParentChildren
        .Where(pc => pc.ParentId == parentId)
        .Select(pc => pc.ChildId)
        .ToListAsync();
    
    if (children.Any())
    {
        var firstChildId = children.First();
        // 用Cookie或Session存储(复用问题1的方法)
        HttpContext.Session.SetString("CurrentChildId", firstChildId);
        return RedirectToAction("ChildDashboard", new { childId = firstChildId });
    }
    else
    {
        // 无子女则跳转创建页面
        return RedirectToAction("CreateChild");
    }
}

全局过滤器自动处理(避免重复代码)

创建全局过滤器:

public class DefaultChildFilter : IActionFilter
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    private readonly ApplicationDbContext _dbContext;

    public DefaultChildFilter(IHttpContextAccessor httpContextAccessor, ApplicationDbContext dbContext)
    {
        _httpContextAccessor = httpContextAccessor;
        _dbContext = dbContext;
    }

    public async void OnActionExecuting(ActionExecutingContext context)
    {
        var user = _httpContextAccessor.HttpContext.User;
        if (user.IsInRole("Parent") && string.IsNullOrEmpty(_httpContextAccessor.HttpContext.Session.GetString("CurrentChildId")))
        {
            var parentId = user.FindFirstValue(ClaimTypes.NameIdentifier);
            var firstChildId = await _dbContext.ParentChildren
                .Where(pc => pc.ParentId == parentId)
                .Select(pc => pc.ChildId)
                .FirstOrDefaultAsync();
            
            if (!string.IsNullOrEmpty(firstChildId))
            {
                _httpContextAccessor.HttpContext.Session.SetString("CurrentChildId", firstChildId);
                context.Result = new RedirectToActionResult("ChildDashboard", "Child", new { childId = firstChildId });
            }
            else
            {
                context.Result = new RedirectToActionResult("CreateChild", "Child", null);
            }
        }
    }

    public void OnActionExecuted(ActionExecutedContext context) { }
}

注册过滤器到Program.cs:

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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 04:05:12