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

如何在ASP.NET MVC导航栏动态更新用户名并跨所有Action保持状态?

解决导航栏无需重复更新ViewBag显示用户名的方案

首先要注意:你当前用静态类Profile存储用户名是线程不安全的,多用户并发访问时会互相覆盖用户信息,建议改用Session、Claims或者认证系统自带的用户标识来存储。

下面是几种无需在每个Action中手动更新ViewBag的方案:

方案1:使用ViewComponent(推荐)

ViewComponent专门用于复用视图逻辑,适合导航栏这种全局复用的部分:

  1. 创建ViewComponent类:
public class UserProfileViewComponent : ViewComponent
{
    private readonly IUserService _userService;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public UserProfileViewComponent(IUserService userService, IHttpContextAccessor httpContextAccessor)
    {
        _userService = userService;
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task<IViewComponentResult> InvokeAsync()
    {
        string accountId = _httpContextAccessor.HttpContext.Session.GetString("AccoountId");
        if (string.IsNullOrEmpty(accountId))
        {
            return View("Empty"); // 返回空视图或者默认内容
        }

        var account = await _userService.GetAccount(accountId);
        var displayName = $"{account.Firstname.Substring(0, 1)}.{account.Lastname}";
        return View("Default", displayName);
    }
}
  1. 创建对应的视图文件:
    在Views/Shared/Components/UserProfile/Default.cshtml中:
<p style="margin:0px">
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-person" viewBox="0 0 16 16">
        <path d="M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6m2-3a2 2 0 1 1-4 0 2 2 0 0 1 4 0m4 8c0 1-1 1-1 1H3s-1 0-1-1 1-4 6-4 6 3 6 4m-1-.004c-.001-.246-.154-.986-.832-1.664C11.516 10.68 10.289 10 8 10s-3.516.68-4.168 1.332c-.678.678-.83 1.418-.832 1.664z" />
    </svg>
    @Model
</p>
  1. 在布局视图_layout.cshtml中替换原来的@ViewBag.Name部分:
<div>
    @await Component.InvokeAsync("UserProfile")
</div>

这样每次渲染布局时,ViewComponent会自动获取用户信息并渲染,无需在任何Action中手动处理。

方案2:使用全局ActionFilter

通过ActionFilter在每个Action执行前统一设置ViewBag:

  1. 创建ActionFilter类:
public class UserProfileActionFilter : IAsyncActionFilter
{
    private readonly IUserService _userService;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public UserProfileActionFilter(IUserService userService, IHttpContextAccessor httpContextAccessor)
    {
        _userService = userService;
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        string accountId = _httpContextAccessor.HttpContext.Session.GetString("AccoountId");
        if (!string.IsNullOrEmpty(accountId))
        {
            var account = await _userService.GetAccount(accountId);
            context.Controller.ViewBag.Name = $"{account.Firstname.Substring(0, 1)}.{account.Lastname}";
        }

        await next(); // 继续执行Action
    }
}
  1. 在Program.cs中注册全局过滤器:
builder.Services.AddControllersWithViews(options =>
{
    options.Filters.Add<UserProfileActionFilter>();
});

这样所有Action执行前都会自动设置ViewBag.Name,布局中可以继续使用@ViewBag.Name,无需在每个Action中重复代码。

方案3:直接在布局视图中读取Session并获取用户信息

如果不想额外创建组件或过滤器,可以直接在布局中调用服务获取用户信息(需要注入服务到视图):

  1. 在_ViewImports.cshtml中添加服务注入:
@inject IUserService UserService
@inject IHttpContextAccessor HttpContextAccessor
  1. 在布局视图中替换@ViewBag.Name部分:
<div>
    @{
        string accountId = HttpContextAccessor.HttpContext.Session.GetString("AccoountId");
        string displayName = string.Empty;
        if (!string.IsNullOrEmpty(accountId))
        {
            var account = await UserService.GetAccount(accountId);
            displayName = $"{account.Firstname.Substring(0, 1)}.{account.Lastname}";
        }
    }
    <p style="margin:0px">
        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-person" viewBox="0 0 16 16">
            <path d="M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6m2-3a2 2 0 1 1-4 0 2 2 0 0 1 4 0m4 8c0 1-1 1-1 1H3s-1 0-1-1 1-4 6-4 6 3 6 4m-1-.004c-.001-.246-.154-.986-.832-1.664C11.516 10.68 10.289 10 8 10s-3.516.68-4.168 1.332c-.678.678-.83 1.418-.832 1.664z" />
        </svg>
        @displayName
    </p>
</div>

这种方式直接在布局中处理,无需修改任何控制器代码,但要注意异步操作在视图中的处理。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 22:32:05