博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
DotNetCore Web应用程序中的Session管理
阅读量:4031 次
发布时间:2019-05-24

本文共 7346 字,大约阅读时间需要 24 分钟。

原文来自互联网,由长沙DotNET技术社区编译。如译文侵犯您的署名权或版权,请联系小编,小编将在24小时内删除。限于译者的能力有限,个别语句翻译略显生硬,还请见谅。

作者简介:Jon(Jonathan)Seeley,一位资深.NET开发者,主要从事Asp.NET/Asp.NET CORE/WPF等技术栈的开发,他的博客地址为https://www.seeleycoder.com/。

查看原文[1]

上个月,我们讨论了DotNetCore Web应用程序中的Cookie管理,[2]并介绍了通用Cookie服务。今天,我们将研究一种用于存储用户数据的替代选项。会话状态是链接到浏览会话的信息的服务器存储,让我们看一下dotnetcore Web应用程序中的通用会话管理技术。

这篇文章的所有代码都可以在我的GitHub上找到[3]

开始之前

如果您在该领域工作了一段时间,您可能已经注意到很多教程向您展示了如何做某事。我的意思是,那就是他们在那里的权利吗?他们通常不会向您显示的是*

正确地

的操作方法*。我今天要做同样的事情。可是等等!请允许我快速解释。今天,我们将在此会话中使用内存中会话状态。

从本质上说,这没错,但也不对。对于任何大小的应用程序,您都希望使用非易失性会话提供程序。例如Redis,数据库,XML文件或其他内容。好吧,Redis实际上也在内存中,对吗?是的,我们不要被语义所困扰。他们将其作为单独的服务运行。

入门

假设您刚刚加载了控制台并输入了以下命令:dotnet new mvc -n SessionManager

现在,您拥有一个崭新的网站品牌,在撰写本文时,该网站正在使用netcoreapp2.2。精彩。

让我们打开它并转到Startup.cs文件,然后在ConfigureServices调用中添加以下几行。这将注册ISession到请求生命周期中,并允许我们从httpcontext访问它。我们还将公开IHttpContextAccessor注入,因为稍后需要使用它。

// have to add this in order to access HttpContext from our own servicesservices.AddSingleton
();// register ISession into our HttpContext lifecycleservices.AddSession(options =>{ options.Cookie.HttpOnly = true;});

ISession无法正常注入,但是您可以通过提供者工厂做一些魔术来将其公开为可注入对象。为了我们的目的,我们不需要,但让我们假装您想要。您可以执行以下操作:

services.AddScoped(provider => provider.GetRequiredService().HttpContext?.Session);

我们还没有完成。我们需要指示管道实际使用会话。弹出该Configure方法,并app.UseSession();在app.UseMvc(...)调用之前添加某处。

添加SessionService

由于我们不会直接注入ISession,因此会出现“我们该怎么办?”的问题。让我们创建一个ISessionService并使用一些通用方法进行设置,以便我们可以序列化/反序列化我们想要的任何内容。如果您查看过Cookie管理方面[4]的信息,则看起来非常相似。

public interface ISessionService{    T Get
(string key); void Set
(string key, T value); void Remove(params string[] keys);}public class SessionService : ISessionService{ private readonly ISession _session; public SessionService(IHttpContextAccessor httpContextRepository) { _session = httpContextRepository.HttpContext.Session; if (_session == null) throw new ArgumentNullException("Session cannot be null."); } public T Get
(string key) { throw new NotImplementedException(); } public void Set
(string key, T value) { throw new NotImplementedException(); } public void Remove(params string[] keys) { throw new NotImplementedException(); }}

在上面的代码块中,我们为ISessionService创建了存根,并为实现创建了框架。我们注入了IHttpContextAccessor,然后从HttpContext访问了Session属性。我们进行检查以确保Session不为空。如果您尝试将其注入通常不具有HttpContext的某个地方(可能是托管服务等),则可能会发生这种情况。我们需要跳回到Startup.cs并添加services.AddScoped<ISessionService, SessionService>();到我们的ConfigureServices调用中。只需在AddSession通话后直接添加即可,但诚实订购无所谓。

实施SessionService

让该服务变得有趣。进入并将以下代码添加到方法中:

public T Get
(string key){ string value = _session.GetString(key); if (string.IsNullOrWhiteSpace(value)) return default(T); return Newtonsoft.Json.JsonConvert.DeserializeObject
(value);}public void Set
(string key, T value){ if (value == null) Remove(key); else _session.SetString(key, Newtonsoft.Json.JsonConvert.SerializeObject(value));}public void Remove(params string[] keys){ if (keys.IsNullOrEmpty()) return; foreach (string key in keys) _session.Remove(key);}

很基本。在该Get方法中,我们从会话中获取字符串值,如果该字符串值不存在,则返回我们类型的默认值。否则,我们将从JSON反序列化为该类型。Set如果传递null或将JSON序列化到会话,我们的方法将删除该值。

我们的Remove方法只是要求会话删除一个值。您不必先检查它是否存在,那样的会话很友好。它确实引用了我添加的扩展方法IsNullOrEmpty,该方法只是检查IEnumerable(在本例中为字符串数组)中是否包含任何内容。

整合代码

打开HomeController.cs并对其进行修改,如下所示:

public class HomeController : Controller{    private const string c_CONTRIVEDSESSIONKEY = "contrived";    private const string c_NAMESESSIONKEY = "basicname";    private readonly ISessionService _sessionService;    public HomeController(ISessionService sessionService)    {        _sessionService = sessionService;    }    public IActionResult Index()    {        var name = _sessionService.Get
(c_NAMESESSIONKEY); var contrived = _sessionService.Get
("contrived") ?? new ContrivedValues { Name = "Guest" }; var viewModel = new HomeViewModel { Name = name, Contrived = contrived }; return View(viewModel); } [HttpPost] public IActionResult PostBasic(NameRequest request) { _sessionService.Set(c_NAMESESSIONKEY, request.Name); return RedirectToAction(nameof(Index)); } [HttpPost] public IActionResult PostContrived(ContrivedValues request) { _sessionService.Set(c_CONTRIVEDSESSIONKEY, request); return RedirectToAction(nameof(Index)); } public IActionResult DeleteContrived() { _sessionService.Remove(c_CONTRIVEDSESSIONKEY); return RedirectToAction(nameof(Index)); } public IActionResult Privacy() { return View(); } [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); }}

在上面的代码中我们注入我们的新ISessionService进HomeController,然后建立一些非常蹩脚的,以及如何与它进行交互的例子。HomeController:Index例如,该方法将尝试从会话中获取字符串值以及一个实例(ContrivedValues如果找不到)或默认实例。我们将它们包装到viewModel中,然后传递到视图中。

HomeController:PostBasic操作方法接受一个NameRequest岗位价值,并将其设置到会话中。PostContrived接一个ContrivedValues帖子并设置它。DeleteContrived将删除我们的会话对象ContrivedValues。

视图模型

显然,以上内容尚未编译。我们需要添加一些模型。进入“模型”文件夹,然后将以下代码添加到新文件中HomeViewModel.cs。

public class HomeViewModel{    public string Name { get; set; }    public ContrivedValues Contrived { get; set; }}public class NameRequest{    public string Name { get; set; }}public class ContrivedValues{    public int? Age { get; set; }    public string Name { get; set; }}

Index.cshtml(视图/主页) 最后,我们需要更新视图以处理该演示。

@model SessionManagerDemo.Models.HomeViewModel@{    ViewData["Title"] = "Home Page";}

Basic Cookie

@if (!string.IsNullOrWhiteSpace(Model.Name)) {

Your name is: @Model.Name

}

Cookie w/Default

Current values:

  • Age: @Model.Contrived.Age
  • Name: @Model.Contrived.Name
Delete

单元测试

我不会在此处粘贴单元测试,但是GitHub代码中[5]有一些单元测试也可以体现其功能。ISession在这种情况下,替换的确很有趣,因为我们使用的是ISession.GetString,它实际上是包装ISession.TryGetValue调用的扩展方法。随意看看,看看我是如何做到这一点的。

结论

DotNetCore Web应用程序中的会话管理非常简单。我们只需要注册会话中间件和会话服务,但是它本身是非常有限的。添加基于通用的包装器可以使我们对过程有更多的控制和灵活性。对于除基本以外的任何功能,您都希望使用某种会话状态服务器,而不是使用此示例所示的内存中状态。

今天发布的所有代码都可以在我的GitHub上找到[6]

References

[1] 查看原文: https://www.seeleycoder.com/blog/session-management-dotnetcore/#more-413

[2] DotNetCore Web应用程序中的Cookie管理,: https://www.seeleycoder.com/blog/cookie-management-asp-net-core/
[3] 我的GitHub上找到: https://github.com/fooberichu150/SessionService
[4] Cookie管理方面: https://www.seeleycoder.com/blog/cookie-management-asp-net-core/
[5] GitHub代码中: https://github.com/fooberichu150/SessionService
[6] 我的GitHub上找到: https://github.com/fooberichu150/SessionService

转载地址:http://fiwdi.baihongyu.com/

你可能感兴趣的文章
计算机的发展史
查看>>
带WiringPi库的交叉编译如何处理一
查看>>
带WiringPi库的交叉笔译如何处理二之软链接概念
查看>>
Spring事务的七种传播行为
查看>>
ES写入找不到主节点问题排查
查看>>
Java8 HashMap集合解析
查看>>
ArrayList集合解析
查看>>
欢迎使用CSDN-markdown编辑器
查看>>
Android计算器实现源码分析
查看>>
Android系统构架
查看>>
Android 跨应用程序访问窗口知识点总结
查看>>
各种排序算法的分析及java实现
查看>>
SSH框架总结(框架分析+环境搭建+实例源码下载)
查看>>
js弹窗插件
查看>>
自定义 select 下拉框 多选插件
查看>>
js判断数组内是否有重复值
查看>>
js获取url链接携带的参数值
查看>>
gdb 调试core dump
查看>>
gdb debug tips
查看>>
arm linux 生成火焰图
查看>>