本文转自: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. Delphi XE8中Android开发有用的资源!

    一,FireMonkey Component Library在XE8帮助(topics.chm)中的位置:FireMonkey Component Library,展示了FireMonkey控件在VC ...

  2. 简单使用postman

    一.get请求 获取学生信息接口文档内容: 简要描述: 获取学生信息接口 请求URL: http://ip/api/user/stu_info 请求方式: get 参数: 参数名 必选 类型 说明 s ...

  3. 'javac' 不是内部或外部命令,也不是可运行的程序

    win10 系统下'javac' 不是内部或外部命令,也不是可运行的程序 1.在系统变量下面配置 JAVA_HOME:你自己的jdk的路径 CLASSPATH= .;%JAVA_HOME%libdt. ...

  4. Phpstudy+DiscuzX安装详解

    1.下载Discuz,地址:https://gitee.com/ComsenzDiscuz/DiscuzX/repository/archive/master.zip 2.下载phpstudy 3.将 ...

  5. jenkins官方文档(中文版)

    https://www.w3cschool.cn/jenkins/

  6. eclipse 与my eclipse区别,IDE

    ecilpse:是一个平台,通过相关插件可以作为c/c++,java,J2EE,PHP,python,Flex等的IDE IDE:集成开发环境(IDE,Integrated Development E ...

  7. mysql ibdata 单独存储

    简介ibdata1 ibdata1文件是InnoDB存储引擎的共享表空间文件,存放位置my.ini 中的 datadir="D:\phpStudy\MySQL\data",目录下. ...

  8. ubuntu系统下如何切换输入法

    如何切换输入法:ctrl+空格键 输入中文时如何翻页:键盘上的 - +两个键 super表示:美式键盘中的Win键

  9. JAVA数据结构--希尔排序

    希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能.这样可以让一个元素可以一次性地朝最终位置前进一大步.然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,但是到了这步,需 ...

  10. Permutation(构造+思维)

    A permutation p is an ordered group of numbers p1,   p2,   ...,   pn, consisting of ndistinct positi ...