提问人:user14554500 提问时间:11/5/2023 更新时间:11/12/2023 访问量:80
如何在核心 razor 网站中存储 int userId asp.net
How to store an int userId in asp.net core razor website
问:
严重努力寻找一个体面的解决方案来跨多个页面访问 int userId 值
所以我不是专家。就在你觉得自己有能力的时候,这样的问题就出现了。
我有一个使用 Identity(使用 VS 2022)的 asp.net 核心 razor Web 应用项目。Identity 正在工作,但我真的想要一个 int userId 而不是一个字符串,但完全放弃了尝试修改 Identity 以使用 int 作为 userId 而不是默认字符串。
因此,我实现了一个数据库表,其中包含我所有的自定义用户属性,其中包含 Identity 字符串 userId 和 int 键。那行得通。
因此,我想在多个页面中获取 int userId。
在剃须刀页面中,我可以使用依赖注入来注入 UserManager userManager。我可以在需要 int userId 并使用 GetUserId 的每个剃刀页面上执行此操作,然后使用带有字符串 userId 的查询查找 int userId。但是,这意味着在我需要 userId 的每个 razor 页面上复制代码,因此这远非一个好的解决方案。我以为我会尝试实现一个静态类来做到这一点,但这似乎无法访问httpContext.Session,所以它不起作用(除非我错过了什么)。
更复杂的是,我认为我可以将 int userId 存储在 Session 中,但它会过期,所以每当我读取 Session 变量时,我都需要检查它是否为 null 并且是一个有效值,如果不是,则通过获取字符串 userId、找到 int userId 并将其保存到会话变量来刷新会话变量。同样,将该代码放在每个页面上并不好。
但是,如果我创建一个类来执行此操作,它没有 dbContext,并且我再次遇到一个问题,即如果它是一个静态类,它似乎无法访问 Session。
这感觉应该是一件很简单的事情,但我让自己陷入了一种螺旋式的“我到底该做什么”的状态。我尝试过做很多谷歌搜索,但似乎没有什么能解决问题
答:
因此,我想在多个页面中获取 int userId。
所有 Razor 页面都继承自类 。在方案中,将“获取 int userid”的 Razor 页面设置为从自定义页面模型继承,如本 SO 文章中所述。PageModel
从基本页面模型继承允许集中代码,否则这些代码将在每个单独的 Razor 页面模型中重复。
继承的类提供对以下内容的访问:DI 服务、 、 等。此外,从基页模型继承的 Razor 页可以访问自定义基页模型中定义的属性。HttpContext
User
下面的示例演示如何使用依赖项注入设置继承的基页模型。
示例注释
此示例使用 DI 服务来替代需要访问数据库服务的方案。
IConfiguration
该属性在继承的基页模型中定义。请注意,该属性是在 Razor 视图页的方法中设置的,因为继承类中的方法使用该对象。此对象在继承类或 Razor 代码隐藏类的构造函数方法中不可用。 一旦代码执行到达该方法,它就可用。
UserIdAsInt
OnGet()
GetUserIdAsInt()
HttpContext
HttpContext
OnGet()
MyBasePageModel.cs
此 C# 类文件可以插入到项目中的任何位置。如果命名空间不是 .using
.cshtml.cs
[ProjectName].Pages
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace WebApplication1.Pages
{
public class MyBasePageModel : PageModel // Inherits from 'PageModel'
{
private readonly IConfiguration _configuration;
public int UserIdAsInt { get; set; }
public MyBasePageModel(IConfiguration configuration)
{
_configuration = configuration;
}
public int GetUserIdAsInt()
{
int? id = HttpContext.Session.GetInt32("UserIdAsInt");
if (id == null)
{
// Get user ID as integer from database
id = 100; // For sample purpose set 'id' variable to a hardcoded value
HttpContext.Session.SetInt32("UserIdAsInt", (int)id);
System.Diagnostics.Debug.WriteLine("User ID retrieved from database");
}
else
{
System.Diagnostics.Debug.WriteLine("User ID retrieved from session");
}
return (int)id;
}
public string GetLoggingLevel()
{
return _configuration["Logging:LogLevel:Default"].ToString();
}
}
}
InheritFromBasePageModel.cshtml.cs
namespace WebApplication1.Pages
{
public class InheritFromBasePageModelModel : MyBasePageModel // Inherits from the custom 'MyBasePageModel' class
{
public string? LoggingLevel { get; set; }
public InheritFromBasePageModelModel(IConfiguration configuration)
: base(configuration: configuration)
{
}
public void OnGet()
{
UserIdAsInt = GetUserIdAsInt();
LoggingLevel = GetLoggingLevel();
}
}
}
InheritFromBasePageModel.cshtml
@page
@model WebApplication1.Pages.InheritFromBasePageModelModel
@{
}
@section Styles {
<style>
p > span {
font-weight: bold;
}
</style>
}
<p>Logging level property from base page model: <span>@Model.LoggingLevel</span></p>
<p>Integer value: <span>@Model.UserIdAsInt</span></p>
程序.cs
// Configure session state
// https://learn.microsoft.com/en-us/aspnet/core/fundamentals/app-state?view=aspnetcore-7.0#configure-session-state
// https://stackoverflow.com/questions/71070698/session-in-asp-net-core-mvc
// "add session middleware in your configuration file"
builder.Services.AddSession(options =>
{
//options.IdleTimeout = TimeSpan.FromMinutes(1);
});
app.UseSession();
(编辑 2023 年 11 月 11 日)
使用 OnPageHandlerExecutionAsync()
重写
上面的基页模型类要求从基页模型继承的每个 Razor 页在方法中添加行。MyBasePageModel.cs
UserIdAsInt = GetUserIdAsInt();
OnGet()
这篇 SO 文章和文章演示如何为从基页模型继承的每个处理程序执行方法,而无需将其添加到每个 Razor 页面。OnGet()
下面是实现重写方法的修改后的类文件。MyBasePageModel.cs
OnPageHandlerExecutionAsync()
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace WebApplication1.Pages
{
public class MyBasePageModel : PageModel
{
private readonly IConfiguration _configuration;
public int UserIdAsInt { get; set; }
public MyBasePageModel(IConfiguration configuration)
{
_configuration = configuration;
}
// https://stackoverflow.com/questions/55030251/razor-pages-call-method-from-base-class-after-all-onget-handlers
// https://www.learnrazorpages.com/razor-pages/filters
// "Model binding completed. Handler has not been executed."
public async override Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
{
if (context.HandlerMethod?.MethodInfo.Name == "OnGet")
{
// Code placed here will execute just before the OnGet()
// method is executed.
UserIdAsInt = await GetUserIdAsInt();
}
await base.OnPageHandlerExecutionAsync(context, next);
}
public async Task<int> GetUserIdAsInt()
{
int? id = HttpContext.Session.GetInt32("UserIdAsInt");
// A valid user ID integer value exists in the 'Session'
// object. Therefore, return this value.
if (id != null)
{
System.Diagnostics.Debug.WriteLine("User ID retrieved from session");
return (int)id;
}
// Get user ID as integer from database
// 'Task.Run()' is used to simulate an async execution
// of a database task.
return await Task.Run(() =>
{
id = 200; // For sample purpose set 'id' variable to a hardcoded value
HttpContext.Session.SetInt32("UserIdAsInt", (int)id);
System.Diagnostics.Debug.WriteLine("User ID retrieved from database");
return (int)id;
});
}
public string? GetLoggingLevel()
{
if (_configuration == null) { return "(Configuration does not exist.)"; }
return _configuration["Logging:LogLevel:Default"]?.ToString() ?? "Unset";
}
}
}
评论
userId
PageModel
HttpContext