本文转自:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/app-state

By Rick Anderson and Steve Smith+

HTTP is a stateless protocol; the Web server treats each HTTP request as an independent request. The server retains no knowledge of variable values that were used in previous requests. This article discusses various approaches to preserving application and user (session) state between requests. +

Application state, unlike session state, applies to all users and sessions.+

Session state

Session state is a feature in ASP.NET Core you can enable that allows you to save and store user data while the user browses your web app. Session data is stored in dictionary on the server and persists data across requests from a browser. A session ID is stored on the client in a cookie. The session ID cookie is sent to server with each request, and the server uses the session ID to fetch the session data. The session ID cookie is per browser, you cannot share session across browsers. Session cookies have no specified timeout, they are deleted when the browser session ends. If a cookie is received for an expired session, then a new session is created using the same Session cookie.+

Session is retained by the server for a limited time after the last request. The default session timeout is 20 minutes, but you can configure session time out. The session data is backed by a cache. Session is ideal for storing user state that is specific to a particular session but which doesn’t need to be persisted permanently. Data is deleted from the backing store either when you call Session.Clear or when the session expires in the data store. The server does not know when the browser is closed or the Session cookie is deleted.+

Warning

Sensitive data should never be stored in session. You can’t guarantee the client will close the browser and clear their session cookie (and some browsers keep them alive across windows). Consequently, you can’t assume that a session is restricted to a single user, the next user may continue with the same session.+

The in-memory session provider stores session data on the server, which can impact scale out. If you run your web app on a server farm, you’ll need to enable sticky sessions to tie each session to a specific server.  Windows Azure Web Sites defaults to sticky sessions (Application Request Routing or ARR). Sticky session can impact scalability and complicate updating your web app. The Redis and SQL Server distributed caches don't require sticky sessions and are the preferred approach to multi-server caching. See Working with a Distributed Cache for more information.+

See Configuring Session below for more details.+

TempData

ASP.NET Core MVC exposes the TempData property on a Controller. TempData can be used for storing transient data that only needs to be available for a single request after the current request. TempData is frequently useful for redirection, when data is needed for more than a single request. TempData is built on top of Session State.+

Cookie-based TempData provider (requires ASP.NET Core 1.1.0 and higher)

To enable the  Cookie-based TempData provider, register the CookieTempDataProvider service in ConfigureServices:+

Copy
C#
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
// Add CookieTempDataProvider after AddMvc and include ViewFeatures.
// using Microsoft.AspNetCore.Mvc.ViewFeatures;
services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();
}

The cookie-based TempData provider does not use Session; data is stored in a cookie on the client. The cookie data is encoded with the Base64UrlTextEncoder. The cookie is encrypted and chunked, so the single cookie size limit does not apply. See CookieTempDataProvider for more information.+

The cookie data is not compressed. Using compression with encryption can lead to security problems such as the CRIME and BREACH attacks.+

Query strings

State from one request can be provided to another request by adding values to the new request's query string. Query strings should never be used with sensitive data. It is also best used with small amounts of data.+

Query strings are useful for capturing state in a persistent manner, allowing links with embedded state to be created and shared through email or social networks. However, no assumption can be made about the user making the request, since URLs with query strings can easily be shared. Care must also be taken to avoid Cross-Site Request Forgery (CSRF) attacks. An attacker could trick a user into visiting a malicious site while authenticated. CSRF are a major form of vulnerability that can be used to steal user data from your app, or take malicious actions on the behalf of the user. Any preserved application or session state needs to protect against CSRF attacks. See Preventing Cross-Site Request Forgery (XSRF/CSRF) Attacks in ASP.NET Core+

Post data and hidden fields

Data can be saved in hidden form fields and posted back on the next request. This is common in multi-page forms.  It’s insecure in that the client can tamper with the data so the server must always revalidate it.+

Cookies

Data can be stored in cookies. Cookies are sent with every request, so the size should be kept to a minimum. Ideally, only an identifier should be used, with the actual data stored somewhere on the server. Cookies are subject to tampering and therefore need to be validated on the server. Cookies are limited by most browsers to 4096 bytes and you have only a limited number of cookies per domain. Although the durability of the cookie on a client is subject to user intervention and expiration, cookies are generally the most durable form of data persistence on the client.+

Cookies are often used for personalization, where content is customized for a known user. In most cases, identification is the issue rather than authentication. Thus, you can typically secure a cookie that is used for identification by storing the user name, account name, or a unique user ID (such as a GUID) in the cookie and then use the cookie to access the user personalization infrastructure of a site.+

HttpContext.Items

The Items collection is the good location to store data that is only needed while processing a given request. Its contents are discarded after each request. It is best used as a means of communicating between components or middleware that operate at different points in time during a request and have no direct way to pass parameters. See Working with HttpContext.Items, below.+

Cache

Caching provides a means of efficiently storing and retrieving data. It provides rules for expiring cached items based on time and other considerations. Learn more about Caching.+

+

Configuring Session

The Microsoft.AspNetCore.Session package provides middleware for managing session state. Enabling the session middleware requires the following in Startup:+

    • Add any of the IDistributedCache memory caches. The IDistributedCache implementation is used as a backing store for session.
    • Call AddSession, which requires NuGet package "Microsoft.AspNetCore.Session".
    • Call UseSession.

+

The following code shows how to set up the in-memory session provider:+

Copy
C#
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using System; public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(); // Adds a default in-memory implementation of IDistributedCache.
services.AddDistributedMemoryCache(); services.AddSession(options =>
{
// Set a short timeout for easy testing.
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.CookieHttpOnly = true;
});
} public void Configure(IApplicationBuilder app)
{
app.UseSession();
app.UseMvcWithDefaultRoute();
}
}

You can reference Session from HttpContext once it is installed and configured.+

Note: Accessing Session before UseSession has been called throwsInvalidOperationException: Session has not been configured for this application or request.+

Attempting to create a new Session (that is, no session cookie has been created) after you have already begun writing to the Response stream throws InvalidOperationException: The session cannot be established after the response has started. The exception can be found in the web server log, it will not be displayed in the browser.+

Loading Session asynchronously

The default session provider in ASP.NET Core will only load the session record from the underlying IDistributedCache store asynchronously if the ISession.LoadAsync method is explicitly called before calling the TryGetValue, Set or Remove methods. Failure to call LoadAsync first will result in the underlying session record being loaded synchronously, which could potentially impact the ability of the app to scale.+

If applications wish to enforce this pattern, they could wrap the DistributedSessionStore and DistributedSession implementations with versions that throw if the LoadAsync method has not been called before calling TryGetValue, Set or Remove, and register the wrapped versions in the services container.+

Implementation Details

Session uses a cookie to track and identify requests from the same browser. By default this cookie is named ".AspNet.Session" and uses a path of "/". The cookie default does not specify a domain. The cookie default is not made available to client-side script on the page (because CookieHttpOnly defaults to true).+

Session defaults can be overridden by using SessionOptions:+

Copy
C#
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(); // Adds a default in-memory implementation of IDistributedCache.
services.AddDistributedMemoryCache(); services.AddSession(options =>
{
options.CookieName = ".AdventureWorks.Session";
options.IdleTimeout = TimeSpan.FromSeconds(10);
});
}

The IdleTimeout is used by the server to determine how long a session can be idle before its contents are abandoned. IdleTimeout is independent of the cookie expiration. Each request that passes through the Session middleware (read from or written to) will reset the timeout.+

Note: Session is non-locking, so if two requests both attempt to modify the contents of session, the last one will win. Session is implemented as a coherent session, which means that all of the contents are stored together. This means that if two requests are modifying different parts of the session (different keys), they may still impact each other.+

Setting and getting Session values

Session is accessed through the Session property on HttpContext. Session is an ISession implementation.+

The following example shows setting and getting an int and a string:+

Copy
C#
public class HomeController : Controller
{
const string SessionKeyName = "_Name";
const string SessionKeyYearsMember = "_YearsMember";
const string SessionKeyDate = "_Date"; public IActionResult Index()
{
// Requires using Microsoft.AspNetCore.Http;
HttpContext.Session.SetString(SessionKeyName, "Rick");
HttpContext.Session.SetInt32(SessionKeyYearsMember, 3);
return RedirectToAction("SessionNameYears");
}
public IActionResult SessionNameYears()
{
var name = HttpContext.Session.GetString(SessionKeyName);
var yearsMember = HttpContext.Session.GetInt32(SessionKeyYearsMember); return Content($"Name: \"{name}\", Membership years: \"{yearsMember}\"");
}

If you add the following extension methods, you can set and get serializable objects to Session:+

Copy
C#
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json; public static class SessionExtensions
{
public static void Set<T>(this ISession session, string key, T value)
{
session.SetString(key, JsonConvert.SerializeObject(value));
} public static T Get<T>(this ISession session,string key)
{
var value = session.GetString(key);
return value == null ? default(T) :
JsonConvert.DeserializeObject<T>(value);
}
}

The following sample shows how to set and get a serializable object:+

Copy
C#
public IActionResult SetDate()
{
// Requires you add the Set extension method mentioned in the article.
HttpContext.Session.Set<DateTime>(SessionKeyDate, DateTime.Now);
return RedirectToAction("GetDate");
} public IActionResult GetDate()
{
// Requires you add the Get extension method mentioned in the article.
var date = HttpContext.Session.Get<DateTime>(SessionKeyDate);
var sessionTime = date.TimeOfDay.ToString();
var currentTime = DateTime.Now.TimeOfDay.ToString(); return Content($"Current time: {currentTime} - "
+ $"session time: {sessionTime}");
}

Working with HttpContext.Items

The HttpContext abstraction provides support for a simple dictionary collection of type IDictionary<object, object>, called Items. This collection is available from the start of an HttpRequest and is discarded at the end of each request. You can access it by  assigning a value to a keyed entry, or by requesting the value for a given key.+

In the sample below, Middleware adds isVerified to the Items collection:+

Copy
C#
app.Use(async (context, next) =>
{
// perform some verification
context.Items["isVerified"] = true;
await next.Invoke();
});

Later in the pipeline, another middleware could access it:+

Copy
C#
app.Run(async (context) =>
{
await context.Response.WriteAsync("Verified request? " + context.Items["isVerified"]);
});

Note: Since keys into Items are simple strings, if you are developing middleware that needs to work across many applications, you may wish to prefix your keys with a unique identifier to avoid key collisions (for example, "MyComponent.isVerified" instead of "isVerified").+

+

Application state data

Use Dependency Injection to make data available to all users.+

    1. Define a service containing the data (for example, a class named MyAppData).

+

Copy
C#
public class MyAppData
{
// Declare properties/methods/etc.
}
    1. Add the service class to ConfigureServices (for example services.AddSingleton<MyAppData>();.
    2. Consume the data service class in each controller:

+

Copy
C#
public class MyController : Controller
{
public MyController(MyAppData myService)
{
// Do something with the service (read some data from it,
// store it in a private field/property, etc.
}
}
}

Common errors when working with session

    • "Unable to resolve service for type 'Microsoft.Extensions.Caching.Distributed.IDistributedCache' while attempting to activate 'Microsoft.AspNetCore.Session.DistributedSessionStore'."

      Commonly caused by not configuring at least one IDistributedCache implementation. See Working with a Distributed Cache and In memory caching for more information

+

Additional Resources

[转]Session and application state in ASP.NET Core的更多相关文章

  1. Prerender Application Level Middleware - ASP.NET Core Middleware

    In the previous post Use Prerender to improve AngularJS SEO, I have explained different solutions at ...

  2. Patterns for application development with ASP.NET Core

    此文章翻译自 NDC { London } 16-20 January 2017 上, Damian Edwards和David Fowler的演讲,如果翻译不周,请大家指出错误. Logging 生 ...

  3. ASP.NET Identity实现分布式Session,Docker+Nginx+Redis+ASP.NET CORE Identity

    零.背景介绍 在学习ASP.NET CORE开发的过程中,身份认证是必须考虑的一项必要的组件.ASP.NET CORE Identity是由微软官方开发的一整套身份认证组件,兼具完整性和自由度.Doc ...

  4. 使用Azure Application Insignhts监控ASP.NET Core应用程序

    Application Insignhts是微软开发的一套监控程序.他可以对线上的应用程序进行全方位的监控,比如监控每秒的请求数,失败的请求,追踪异常,对每个请求进行监控,从http的耗时,到SQL查 ...

  5. ASP.NET Core 2 学习笔记(十一)Cookies & Session

    基本上HTTP是没有记录状态的协定,但可以通过Cookies将Request来源区分出来,并将部分数据暂存于Cookies及Session,是写网站常用的用户数据暂存方式.本篇将介绍如何在ASP.NE ...

  6. SessionState in ASP.NET Core(转载)

    问: In asp.net mvc we used to decorate controller for disabling session state by using attribute as [ ...

  7. Prerender Application Level Middleware - ASP.NET HttpModule

    In the previous post Use Prerender to improve AngularJS SEO, I have explained different solutions at ...

  8. ASP.NET Core 1.0 入门——了解一个空项目

    var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...

  9. Working with Data » 使用Visual Studio开发ASP.NET Core MVC and Entity Framework Core初学者教程

    原文地址:https://docs.asp.net/en/latest/data/ef-mvc/intro.html The Contoso University sample web applica ...

随机推荐

  1. linux系统上安装mysql5.6(详细步骤)

    为了学习mycat 尝试在虚拟机上装mysql(看了别人的博客比划着安装),但装了两次都没成功.因此总结了如下步骤 有需要的朋友可以试下(linux需要联网) mysql-5.6.26.tar.gz百 ...

  2. 洛谷P3779 [SDOI2017]龙与地下城(概率论+Simpson+FFT)

    题面 传送门 题解 orz shadowice 正态分布 正态分布是随机变量\(X\)的一种概率分布形式.它用一个期望\(\mu\)和方差\(\sigma^2\)就可以描述,记为\(N(\mu,\si ...

  3. MongoSQL 复制数据表报错

    报错内容为: [thread1] SyntaxError: identifier starts immediately after numeric literal @(shell):1:2 解决方案: ...

  4. Pycharm使用的一些问题!!!

    1.pycharm如何更改主题.如何更改字体的大小? 2.pycharm如何import第三方库? 1.更改主题和字体大小 主题变暗,字体变大! 2.如何导入第三方库?

  5. SQL语句优化 -- 以Mysql为例

     本文参考下面的文章:    1: [真·干货]MySQL 索引及优化实战 2:  Mysql语句的执行过程 3:  sql优化的几种方法 我将  sql语句优化分为三个方面,(此处不包括 业务逻辑的 ...

  6. 谈谈php中抽象类和接口的区别

    php中抽象类和接口的区别 1) 概念 面向对象的三大概念:封装,继承,多态 把属性和方法封装起来就是类.        一个类的属性和方法被另外的类复制就是继承,PHP里面的任何类都可以被继承,被继 ...

  7. 百度地图中使用mouseover事件获取经纬度时无法拿到鼠标所在位置的经纬度。

    用百度2.0的话使用mousemove 鼠标在地图区域移动过程中触发此事件.mouseover参数e中没有point参数

  8. PHP生成pdf文档

    首先需要去github下载tcpdf类库 require_once('./tcpdf/tcpdf.php');         date_default_timezone_get('Asia/Shan ...

  9. Exadata 18.1新特性--云平台存储节点升级

    1.传统方式的存储节点升级流程: (1).将存储节点升级包下载到数据库服务器,通常是DB01上. (2).解压缩存储节点升级包. (3).用升级包中的patchmgr工具滚动或非滚动地升级每个存储节点 ...

  10. redux超易学三篇之三(一个逻辑完整的react-redux)

    配合源代码学习吧~ : 我是源代码 这一分支讲的是 如何完整地(不包含优化,也没有好看的页面) 搭建一个 增删改查 的 react-redux 系统 不同于上一节的 react-redux,这里主要采 ...