.NET Core中如何获取用户语言ID并设为全局变量按需调用
工具
- Visual Studio 2022 社区版
- .NET Core 7.0
- Razor Pages
需求说明
为减少应用中数据库调用次数,我希望创建一个存储当前用户语言ID的全局变量,在用户登录时为其赋值。之后可在各页面模型中按需调用该变量,以此定义UI语言。我已为全局变量声明了一个类,但无法继续推进:既无法获取当前用户ID,也无法调用数据库表...
问题
如何正确实现这一功能?
代码示例
namespace MyApp.Models { private readonly Models.ApplicationDbContext _context; public class Class { var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); private int langId = _context.Languages.where(x=>x.UserId = userId).FirstOrDefault().Id; public int GetLangId { get { return langId; } set { langId = value; } } } }
解决方案
你的代码存在几个核心问题:直接在类字段中写业务逻辑、无法直接访问User对象、依赖注入位置错误、未处理空引用风险,而且静态类/全局变量会在多用户环境下冲突——每个用户的语言ID是独立的,不能共用同一存储。下面提供两种可行方案:
方案一:登录时将语言ID写入用户Claims(推荐)
这种方式最直接,登录后语言ID会随用户身份信息一起传递,无需额外查询数据库:
- 在登录逻辑中(比如
Login.cshtml.cs的OnPostAsync方法),获取用户的语言ID并添加到Claims:
var user = await _userManager.FindByNameAsync(Input.Email); if (user != null) { // 从数据库获取用户语言ID,没有则设默认值1 var language = await _context.Languages.FirstOrDefaultAsync(x => x.UserId == user.Id); var langId = language?.Id ?? 1; // 创建ClaimsIdentity并添加语言ID Claim var claims = new List<Claim> { new Claim(ClaimTypes.NameIdentifier, user.Id), new Claim("LangId", langId.ToString()) // 其他必要Claims... }; var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity)); return RedirectToPage("/Index"); }
- 在任意页面模型或服务中获取语言ID:
// 页面模型中直接获取 var langId = int.Parse(User.FindFirstValue("LangId")); // 服务中需注入IHttpContextAccessor来访问用户信息 public class MyService { private readonly IHttpContextAccessor _httpContextAccessor; public MyService(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } public int GetCurrentLangId() { var langIdStr = _httpContextAccessor.HttpContext?.User.FindFirstValue("LangId"); return int.TryParse(langIdStr, out int id) ? id : 1; } }
方案二:使用Scoped服务存储语言ID
适合需要动态修改语言ID的场景,Scoped服务的生命周期与请求一致,每个用户请求会创建独立实例:
- 定义语言提供器接口和实现类:
public interface ILanguageProvider { int LangId { get; set; } } public class LanguageProvider : ILanguageProvider { public int LangId { get; set; } }
- 在
Program.cs中注册为Scoped服务:
builder.Services.AddScoped<ILanguageProvider>(); // 注册IHttpContextAccessor(如果服务中需要访问用户信息) builder.Services.AddHttpContextAccessor();
- 登录时设置语言ID:
在Login.cshtml.cs中注入ILanguageProvider和ApplicationDbContext:
private readonly ILanguageProvider _languageProvider; private readonly ApplicationDbContext _context; public LoginModel(ILanguageProvider languageProvider, ApplicationDbContext context) { _languageProvider = languageProvider; _context = context; } public async Task<IActionResult> OnPostAsync() { // 登录验证逻辑... var user = await _userManager.FindByNameAsync(Input.Email); if (user != null) { var language = await _context.Languages.FirstOrDefaultAsync(x => x.UserId == user.Id); _languageProvider.LangId = language?.Id ?? 1; // 完成登录逻辑... return RedirectToPage("/Index"); } // 错误处理... }
- 在其他页面模型中获取:
public class IndexModel : PageModel { private readonly ILanguageProvider _languageProvider; public int CurrentLangId { get; set; } public IndexModel(ILanguageProvider languageProvider) { _languageProvider = languageProvider; } public void OnGet() { CurrentLangId = _languageProvider.LangId; // 用CurrentLangId设置UI语言... } }
代码错误修正说明
你提供的代码需要调整以下几点才能运行:
- 依赖注入的
_context必须放在类的构造函数中,不能直接在类外声明 - 获取
User需要通过IHttpContextAccessor,不能直接在类字段中访问 - 必须处理
FirstOrDefault()返回null的情况,避免空引用异常 - 不能用静态类存储用户专属数据,会导致多用户数据冲突
内容的提问来源于stack exchange,提问作者Fillo
相关产品推荐
相关产品推荐

