参考:ASP.NET Core 中的会话和应用状态

状态管理

可以使用几种方法存储状态。 本主题稍后将对每个方法进行介绍。

存储方法 存储机制
Cookie HTTP Cookie(可能包括使用服务器端应用代码存储的数据)
Session state HTTP Cookie 和服务器端应用代码
TempData HTTP Cookie 或会话状态
Query strings HTTP 查询字符串
Hidden fields HTTP 窗体字段
HttpContext.Items 服务器端应用代码
缓存 服务器端应用代码
依赖关系注入 服务器端应用代码

Cookie

因为 Cookie 随请求发送,所以应该控制其大小。理想情况是 Cookie 中仅存储用户标识符。

Session state

会话状态是用户浏览 Web 应用时 ASP.NET Core 存储用户数据的方案。会话状态使用应用维护的存储来保存客户端所有请求的数据。会话数据由缓存支持并被视为临时数据 —— 站点应在没有会话数据的情况下继续运行。

ASP.NET Core 通过向客户端提供包含会话 ID 的 Cookie 来维护会话状态,该会话 ID 与每个请求一起发送到应用。应用使用会话 ID 来获取会话数据。

Session state 具有以下行为:

  • 由于会话 Cookie 特定于浏览器,因此不能跨浏览器共享会话
  • 浏览器会话结束时删除会话 Cookie
  • 如果收到过期的会话 Cookie,则创建使用相同会话 Cookie 的新会话
  • 不会保留空会话 - 会话中必须设置了至少一个值以保存所有请求的会话。会话未保留时,为每个新的请求生成新会话 ID
  • 应用在上次请求后保留会话的时间有限。应用设置会话超时,或者使用 20 分钟的默认值。会话状态适用于存储特定于特定会话的用户数据,但该数据无需永久的会话存储
  • 调用 ISession.Clear 实现或者会话过期时,会删除会话数据
  • 没有默认机制告知客户端浏览器已关闭或者客户端上的会话 Cookie 被删除或过期的应用代码

警告
请勿将敏感数据存储在会话状态中。用户可能不会关闭浏览器并清除会话 Cookie。某些浏览器会保留所有浏览器窗口中的有效会话 Cookie。会话可能不限于单个用户 - 下一个用户可能继续使用同一会话 Cookie 浏览应用。

配置 Session state

要在 ASP.NET Core 中启用 Session state,Startup 必须包含:

ASP.NET Core 会话和应用状态 - 图1

注:中间件的顺序很重要。 在前面的示例中,在 UseMvc 之后调用 UseSession 时会发生 InvalidOperationException 异常。 有关详细信息,请参阅中间件排序

配置好 Session state 后,HttpContext.Session 就可以使用了。

官方教程还有更多关于 Session state 的配置、设置和获取的相关内容,此处不再赘述。

TempData

TempData 在 ASP.NET Core 2.0 或更高版本中,默认基于 Cookie 实现。

通过配置也可以基于 Session state 实现 TempData:
ASP.NET Core 会话和应用状态 - 图2

HttpContext.Items

处理单个请求时,使用 HttpContext.Items 集合存储数据。处理请求后,放弃集合的内容。通常使用 Items 集合允许组件或中间件在请求期间在不同时间点操作且没有直接传递参数的方法时进行通信。

示例:中间件将 isVerified 添加到 Items 集合。

  1. app.Use(async (context, next) =>
  2. {
  3. // perform some verification
  4. context.Items["isVerified"] = true;
  5. await next.Invoke();
  6. });

然后,在管道中,另一个中间件可以使用 isVerified 值:

  1. app.Run(async (context) =>
  2. {
  3. await context.Response.WriteAsync($"Verified: {context.Items["isVerified"]}");
  4. });

缓存

缓存是存储和检索数据的有效方法。应用可以控制缓存项的生存期。

缓存数据未与特定请求、用户或会话相关联。换句话说请不要缓存特定于用户的数据

依赖关系注入

使用依赖关系注入可向所有用户提供数据:

  1. 定义一项包含数据的服务。 例如,定义一个名为 MyAppData 的类:

    1. public class MyAppData
    2. {
    3. // Declare properties and methods
    4. }
  2. 将服务类添加到 Startup.ConfigureServices

    1. public void ConfigureServices(IServiceCollection services)
    2. {
    3. services.AddSingleton<MyAppData>();
    4. }
  3. 使用数据服务类:

    1. public class IndexModel : PageModel
    2. {
    3. public IndexModel(MyAppData myService)
    4. {
    5. // Do something with the service
    6. // Examples: Read data, store in a field or property
    7. }
    8. }