在 ASP.Net 核心 Razor 页面中使用会话包装器



为了改进应用程序中的会话处理,我们希望创建一个包装类,该类通过属性管理会话访问(以防止使用字符串时的常见问题(。

像这样:

public class Wrapper
{
public string Username
{
get { return HttpContext.Current.Session.GetString("username"); }
set { HttpContext.Current.Session.SetString("username", value); }
}
}

有很多示例说明如何在经典 ASP.Net 中实现这一点,但我们无法将它们移植到 ASP.Net Core。关于 ASP.Net Core 中的会话包装器的唯一另一个问题(我可以找到(是使用单例,我们发现它不适合我们的情况。

我们的问题归结为两个主要问题:

  • 如何正确包装和访问另一个类中的当前会话(避免反模式和安全问题(
  • 如何在我们的应用程序中共享类

我们决定使用 ASP.Net Core 的依赖注入功能,因为它似乎非常适合这项工作。要访问服务内部的会话,IHttpContextAccessor 是必需的。如 David Fowler 的 ASP.NET 核心诊断方案中所述,建议不要将IHttpContextAccessor.HttpContext存储在字段中,但使用作用域服务应该可以缓解此问题,因为它是为每个请求创建的。

我们的设置

在这里,我们使用HttpContextAccessor来引用当前会话。通过使用属性来限制对会话的访问(字符串可以进一步替换为常量(。

public class SessionService
{
private readonly ISession _session;
public SessionService(IHttpContextAccessor accessor)
{
_session = accessor.HttpContext.Session;
}
public string Username
{
get { return _session.GetString("username"); }
set { _session.SetString("username", value); }
}
}

然后将会话包装器配置为Startup.cs内的作用域服务:

public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
// ...
// Register the service we use for session handling.
services.AddScoped<SessionService>();
}

最后但并非最不重要的一点是,该服务被注入到我们的页面模型中,并用于通过其属性访问会话。

public class IndexModel : PageModel
{
private readonly ILogger<IndexModel> _logger;
private readonly SessionService _session;
public IndexModel(ILogger<IndexModel> logger, SessionService session)
{
_logger = logger;
_session = session;
}
public void OnPost()
{
// Set the session variable.
_session.Username = "foo@bar";
}
}

我发布答案是希望获得有关我的解决方案的反馈,并为其他为此苦苦挣扎的人提供参考点。

最新更新