Estado de sessão e aplicativo no ASP.NET CoreSession and app state in ASP.NET Core

Por Rick Anderson, Steve Smith, Diana LaRose e Luke LathamBy Rick Anderson, Steve Smith, Diana LaRose, and Luke Latham

O HTTP é um protocolo sem estado.HTTP is a stateless protocol. Sem realizar etapas adicionais, as solicitações HTTP são mensagens independentes que não mantêm os valores de usuário nem o estado do aplicativo.Without taking additional steps, HTTP requests are independent messages that don't retain user values or app state. Este artigo descreve várias abordagens para preservar dados do usuário e estado de aplicativo entre solicitações.This article describes several approaches to preserve user data and app state between requests.

Exibir ou baixar código de exemplo (como baixar)View or download sample code (how to download)

Gerenciamento de estadoState management

O estado pode ser armazenado usando várias abordagens.State can be stored using several approaches. Cada abordagem é descrita posteriormente neste tópico.Each approach is described later in this topic.

Abordagem de armazenamentoStorage approach Mecanismo de armazenamentoStorage mechanism
CookiesCookies Cookies HTTP (podem incluir dados armazenados usando o código de aplicativo do lado do servidor)HTTP cookies (may include data stored using server-side app code)
Estado de sessãoSession state Cookies HTTP e o código de aplicativo do lado do servidorHTTP cookies and server-side app code
TempDataTempData Estado de sessão ou cookies HTTPHTTP cookies or session state
Cadeias de consultaQuery strings Cadeias de caracteres de consulta HTTPHTTP query strings
Campos ocultosHidden fields Campos de formulário HTTPHTTP form fields
HttpContext.ItemsHttpContext.Items Código do aplicativo do lado do servidorServer-side app code
CacheCache Código do aplicativo do lado do servidorServer-side app code
Injeção de dependênciaDependency Injection Código do aplicativo do lado do servidorServer-side app code

CookiesCookies

Cookies armazenam dados entre solicitações.Cookies store data across requests. Como os cookies são enviados com cada solicitação, seu tamanho deve ser reduzido ao mínimo.Because cookies are sent with every request, their size should be kept to a minimum. Idealmente, somente um identificador deve ser armazenado em um cookie com os dados armazenados pelo aplicativo.Ideally, only an identifier should be stored in a cookie with the data stored by the app. A maioria dos navegadores restringe o tamanho do cookie a 4.096 bytes.Most browsers restrict cookie size to 4096 bytes. Somente um número limitado de cookies está disponível para cada domínio.Only a limited number of cookies are available for each domain.

Uma vez que os cookies estão sujeitos à adulteração, eles devem ser validados pelo aplicativo.Because cookies are subject to tampering, they must be validated by the app. Os cookies podem ser excluídos por usuários e expirarem em clientes.Cookies can be deleted by users and expire on clients. No entanto, os cookies geralmente são a forma mais durável de persistência de dados no cliente.However, cookies are generally the most durable form of data persistence on the client.

Frequentemente, cookies são usados para personalização quando o conteúdo é personalizado para um usuário conhecido.Cookies are often used for personalization, where content is customized for a known user. O usuário é apenas identificado, e não autenticado, na maioria dos casos.The user is only identified and not authenticated in most cases. O cookie pode armazenar o nome do usuário, o nome da conta ou a ID de usuário único (como um GUID).The cookie can store the user's name, account name, or unique user ID (such as a GUID). Você pode usar o cookie para acessar as configurações personalizadas do usuário, como cor preferida da tela de fundo do site.You can then use the cookie to access the user's personalized settings, such as their preferred website background color.

Esteja ciente do RGPD (Regulamento Geral sobre a Proteção de Dados) da União Europeia ao emitir cookies e lidar com questões de privacidade.Be mindful of the European Union General Data Protection Regulations (GDPR) when issuing cookies and dealing with privacy concerns. Para obter mais informações, veja Suporte ao RGPD (Regulamento Geral sobre a Proteção de Dados) no ASP.NET Core.For more information, see General Data Protection Regulation (GDPR) support in ASP.NET Core.

Estado de sessãoSession state

Estado de sessão é um cenário do ASP.NET Core para o armazenamento de dados de usuário enquanto o usuário procura um aplicativo Web.Session state is an ASP.NET Core scenario for storage of user data while the user browses a web app. Estado de sessão usa um armazenamento mantido pelo aplicativo para que os dados persistam entre solicitações de um cliente.Session state uses a store maintained by the app to persist data across requests from a client. Os dados da sessão são apoiados por um cache e considerados dados efêmeros—o site deve continuar funcionando sem os dados da sessão.The session data is backed by a cache and considered ephemeral data—the site should continue to function without the session data. Os dados críticos do aplicativo devem ser armazenados no banco de dados do usuário e armazenados em cache na sessão apenas como uma otimização de desempenho.Critical application data should be stored in the user database and cached in session only as a performance optimization.

Observação

A sessão não é compatível com os aplicativos SignalR porque um Hub SignalR pode ser executado independente de um contexto HTTP.Session isn't supported in SignalR apps because a SignalR Hub may execute independent of an HTTP context. Por exemplo, isso pode ocorrer quando uma solicitação de sondagem longa é mantida aberta por um hub além do tempo de vida do contexto HTTP da solicitação.For example, this can occur when a long polling request is held open by a hub beyond the lifetime of the request's HTTP context.

O ASP.NET Core mantém o estado de sessão fornecendo um cookie para o cliente que contém uma ID de sessão, que é enviada para o aplicativo com cada solicitação.ASP.NET Core maintains session state by providing a cookie to the client that contains a session ID, which is sent to the app with each request. O aplicativo usa a ID da sessão para buscar os dados da sessão.The app uses the session ID to fetch the session data.

Estado de sessão exibe os seguintes comportamentos:Session state exhibits the following behaviors:

  • Uma vez que o cookie da sessão é específico ao navegador, não é possível compartilhar sessões entre navegadores.Because the session cookie is specific to the browser, sessions aren't shared across browsers.
  • Cookies da sessão são excluídos quando a sessão do navegador termina.Session cookies are deleted when the browser session ends.
  • Se um cookie for recebido de uma sessão expirada, será criada uma nova sessão que usa o mesmo cookie de sessão.If a cookie is received for an expired session, a new session is created that uses the same session cookie.
  • Sessões vazias não são mantidas—a sessão deve ter pelo menos um valor definido nela para que mantenha a sessão entre solicitações.Empty sessions aren't retained—the session must have at least one value set into it to persist the session across requests. Quando uma sessão não é mantida, uma nova ID de sessão é gerada para cada nova solicitação.When a session isn't retained, a new session ID is generated for each new request.
  • O aplicativo mantém uma sessão por um tempo limitado após a última solicitação.The app retains a session for a limited time after the last request. O aplicativo define o tempo limite da sessão ou usa o valor padrão de 20 minutos.The app either sets the session timeout or uses the default value of 20 minutes. Estado de sessão é ideal para armazenar dados de usuário específicos para uma sessão em particular, mas em que os dados não requerem armazenamento permanente entre sessões.Session state is ideal for storing user data that's specific to a particular session but where the data doesn't require permanent storage across sessions.
  • Dados da sessão são excluídos quando a implementação ISession.Clear é chamada ou quando a sessão expira.Session data is deleted either when the ISession.Clear implementation is called or when the session expires.
  • Não há nenhum mecanismo padrão para informar o código do aplicativo de que um navegador cliente foi fechado ou quando o cookie de sessão foi excluído ou expirou no cliente.There's no default mechanism to inform app code that a client browser has been closed or when the session cookie is deleted or expired on the client.
  • Os modelos de páginas do ASP.NET Core MVC e Razor incluem suporte ao RGPD (Regulamento Geral sobre a Proteção de Dados).The ASP.NET Core MVC and Razor pages templates include support for General Data Protection Regulation (GDPR). Os cookies do estado de sessão não são marcados como essenciais por padrão, portanto, o estado de sessão não é funcional, a menos que o rastreamento seja permitido pelo visitante do site.Session state cookies aren't marked essential by default, so session state isn't functional unless tracking is permitted by the site visitor. Para obter mais informações, consulte Suporte a Regulamento Geral sobre a Proteção de Dados (GDPR) no ASP.NET Core.For more information, see Suporte a Regulamento Geral sobre a Proteção de Dados (GDPR) no ASP.NET Core.

Aviso

Não armazene dados confidenciais no estado de sessão.Don't store sensitive data in session state. O usuário não pode fechar o navegador e limpar o cookie de sessão.The user might not close the browser and clear the session cookie. Alguns navegadores mantêm cookies de sessão válidos entre as janelas do navegador.Some browsers maintain valid session cookies across browser windows. Uma sessão não pode ser restringida a um único usuário—o próximo usuário pode continuar a procurar o aplicativo com o mesmo cookie de sessão.A session might not be restricted to a single user—the next user might continue to browse the app with the same session cookie.

O provedor de cache na memória armazena dados de sessão na memória do servidor em que o aplicativo reside.The in-memory cache provider stores session data in the memory of the server where the app resides. Em um cenário de farm de servidores:In a server farm scenario:

Configurar o estado de sessãoConfigure session state

O pacote Microsoft.AspNetCore.Session, incluído no metapacote Microsoft.AspNetCore.App, fornece middleware para gerenciar o estado de sessão.The Microsoft.AspNetCore.Session package, which is included in the Microsoft.AspNetCore.App metapackage, provides middleware for managing session state. Para habilitar o middleware da sessão, Startup deve conter:To enable the session middleware, Startup must contain:

O código a seguir mostra como configurar o provedor de sessão na memória com uma implementação padrão na memória de IDistributedCache:The following code shows how to set up the in-memory session provider with a default in-memory implementation of IDistributedCache:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDistributedMemoryCache();

        services.AddSession(options =>
        {
            // Set a short timeout for easy testing.
            options.IdleTimeout = TimeSpan.FromSeconds(10);
            options.Cookie.HttpOnly = true;
            // Make the session cookie essential
            options.Cookie.IsEssential = true;
        });

        services.AddMvc()
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseSession();
        app.UseHttpContextItemsMiddleware();
        app.UseMvc();
    }
}

A ordem do middleware é importante.The order of middleware is important. No exemplo anterior, uma exceção InvalidOperationException ocorre quando UseSession é invocado após UseMvc.In the preceding example, an InvalidOperationException exception occurs when UseSession is invoked after UseMvc. Para obter mais informações, veja Ordenação de Middleware.For more information, see Middleware Ordering.

HttpContext.Session estará disponível depois que o estado de sessão for configurado.HttpContext.Session is available after session state is configured.

HttpContext.Session não pode ser acessado antes que UseSession tenha sido chamado.HttpContext.Session can't be accessed before UseSession has been called.

Não é possível criar uma nova sessão com um novo cookie de sessão depois que o aplicativo começou a gravar no fluxo de resposta.A new session with a new session cookie can't be created after the app has begun writing to the response stream. A exceção é registrada no log do servidor Web e não é exibida no navegador.The exception is recorded in the web server log and not displayed in the browser.

Carregue o estado de sessão de maneira assíncronaLoad session state asynchronously

O provedor de sessão padrão no ASP.NET Core carregará os registros da sessão do repositório de backup IDistributedCache subjacente de maneira assíncrona somente se o método ISession.LoadAsync for chamado explicitamente antes dos métodos TryGetValue, Set ou Remove.The default session provider in ASP.NET Core loads session records from the underlying IDistributedCache backing store asynchronously only if the ISession.LoadAsync method is explicitly called before the TryGetValue, Set, or Remove methods. Se LoadAsync não for chamado primeiro, o registro de sessão subjacente será carregado de maneira síncrona, o que pode incorrer em uma penalidade de desempenho em escala.If LoadAsync isn't called first, the underlying session record is loaded synchronously, which can incur a performance penalty at scale.

Para que aplicativos imponham esse padrão, encapsule as implementações DistributedSessionStore e DistributedSession com versões que geram uma exceção se o método LoadAsync não for chamado antes de TryGetValue, Set ou Remove.To have apps enforce this pattern, wrap the DistributedSessionStore and DistributedSession implementations with versions that throw an exception if the LoadAsync method isn't called before TryGetValue, Set, or Remove. Registre as versões encapsuladas no contêiner de serviços.Register the wrapped versions in the services container.

Opções da sessãoSession options

Para substituir os padrões da sessão, use SessionOptions.To override session defaults, use SessionOptions.

OpçãoOption DescriçãoDescription
CookieCookie Determina as configurações usadas para criar o cookie.Determines the settings used to create the cookie. Name assume como padrão SessionDefaults.CookieName (.AspNetCore.Session).Name defaults to SessionDefaults.CookieName (.AspNetCore.Session). Path assume como padrão SessionDefaults.CookiePath (/).Path defaults to SessionDefaults.CookiePath (/). SameSite assume como padrão SameSiteMode.Lax (1).SameSite defaults to SameSiteMode.Lax (1). HttpOnly assume true como padrão .HttpOnly defaults to true. IsEssential assume false como padrão.IsEssential defaults to false.
IdleTimeoutIdleTimeout O IdleTimeout indica por quanto tempo a sessão pode ficar ociosa antes de seu conteúdo ser abandonado.The IdleTimeout indicates how long the session can be idle before its contents are abandoned. Cada acesso à sessão redefine o tempo limite.Each session access resets the timeout. Essa configuração aplica-se somente ao conteúdo da sessão, não ao cookie.This setting only applies to the content of the session, not the cookie. O padrão é de 20 minutos.The default is 20 minutes.
IOTimeoutIOTimeout O tempo máximo permitido para carregar uma sessão do repositório ou para confirmá-la de volta para o repositório.The maximum amount of time allowed to load a session from the store or to commit it back to the store. Essa configuração pode se aplicar somente a operações assíncronas.This setting may only apply to asynchronous operations. Esse tempo limite pode ser desabilitado usando InfiniteTimeSpan.This timeout can be disabled using InfiniteTimeSpan. O padrão é 1 minuto.The default is 1 minute.

A sessão usa um cookie para rastrear e identificar solicitações de um único navegador.Session uses a cookie to track and identify requests from a single browser. Por padrão, esse cookie se chama .AspNetCore.Session, e usa um caminho de /.By default, this cookie is named .AspNetCore.Session, and it uses a path of /. Uma vez que o padrão do cookie não especifica um domínio, ele não fica disponível para o script do lado do cliente na página (porque HttpOnly usa true como padrão).Because the cookie default doesn't specify a domain, it isn't made available to the client-side script on the page (because HttpOnly defaults to true).

Para substituir os padrões de sessão do cookie, use SessionOptions:To override cookie session defaults, use SessionOptions:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddDistributedMemoryCache();

    services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    services.AddSession(options =>
    {
        options.Cookie.Name = ".AdventureWorks.Session";
        options.IdleTimeout = TimeSpan.FromSeconds(10);
        options.Cookie.IsEssential = true;
    });
}

O aplicativo usa a propriedade IdleTimeout para determinar por quanto tempo uma sessão pode ficar ociosa antes de seu conteúdo no cache do servidor ser abandonado.The app uses the IdleTimeout property to determine how long a session can be idle before its contents in the server's cache are abandoned. Essa propriedade é independente da expiração do cookie.This property is independent of the cookie expiration. Cada solicitação que passa pelo Middleware da Sessão redefine o tempo limite.Each request that passes through the Session Middleware resets the timeout.

Estado de sessão é sem bloqueio.Session state is non-locking. Se duas solicitações tentarem simultaneamente modificar o conteúdo de uma sessão, a última solicitação substituirá a primeira.If two requests simultaneously attempt to modify the contents of a session, the last request overrides the first. Session é implementado como uma sessão coerente, o que significa que todo o conteúdo é armazenado junto.Session is implemented as a coherent session, which means that all the contents are stored together. Quando duas solicitações buscam modificar valores de sessão diferentes, a última solicitação pode substituir as alterações de sessão feitas pelo primeira.When two requests seek to modify different session values, the last request may override session changes made by the first.

Definir e obter valores de SessionSet and get Session values

Estado de sessão é acessado de uma classe PageModel Razor Pages ou classe Controlador MVC com HttpContext.Session.Session state is accessed from a Razor Pages PageModel class or MVC Controller class with HttpContext.Session. Esta propriedade é uma implementação de ISession.This property is an ISession implementation.

A implementação de ISession fornece vários métodos de extensão para definir e recuperar valores de inteiro e cadeia de caracteres.The ISession implementation provides several extension methods to set and retrieve integer and string values. Os métodos de extensão estão no namespace Microsoft.AspNetCore.Http (adicione uma instrução using Microsoft.AspNetCore.Http; para acessar os métodos de extensão) quando o pacote Microsoft.AspNetCore.Http.Extensions for referenciado pelo projeto.The extension methods are in the Microsoft.AspNetCore.Http namespace (add a using Microsoft.AspNetCore.Http; statement to gain access to the extension methods) when the Microsoft.AspNetCore.Http.Extensions package is referenced by the project. Ambos os pacotes são incluídos no metapacote Microsoft.AspNetCore.App.Both packages are included in the Microsoft.AspNetCore.App metapackage.

Métodos de extensão ISession:ISession extension methods:

O exemplo a seguir recupera o valor da sessão para a chave IndexModel.SessionKeyName (_Name no aplicativo de exemplo) em uma página do Razor Pages:The following example retrieves the session value for the IndexModel.SessionKeyName key (_Name in the sample app) in a Razor Pages page:

@page
@using Microsoft.AspNetCore.Http
@model IndexModel

...

Name: @HttpContext.Session.GetString(IndexModel.SessionKeyName)

O exemplo a seguir mostra como definir e obter um número inteiro e uma cadeia de caracteres:The following example shows how to set and get an integer and a string:

public class IndexModel : PageModel
{
    public const string SessionKeyName = "_Name";
    public const string SessionKeyAge = "_Age";
    const string SessionKeyTime = "_Time";

    public string SessionInfo_Name { get; private set; }
    public string SessionInfo_Age { get; private set; }
    public string SessionInfo_CurrentTime { get; private set; }
    public string SessionInfo_SessionTime { get; private set; }
    public string SessionInfo_MiddlewareValue { get; private set; }

    public void OnGet()
    {
        // Requires: using Microsoft.AspNetCore.Http;
        if (string.IsNullOrEmpty(HttpContext.Session.GetString(SessionKeyName)))
        {
            HttpContext.Session.SetString(SessionKeyName, "The Doctor");
            HttpContext.Session.SetInt32(SessionKeyAge, 773);
        }

        var name = HttpContext.Session.GetString(SessionKeyName);
        var age = HttpContext.Session.GetInt32(SessionKeyAge);

Todos os dados de sessão devem ser serializados para habilitar um cenário de cache distribuído, mesmo ao usar o cache na memória.All session data must be serialized to enable a distributed cache scenario, even when using the in-memory cache. Cadeia de caracteres mínima e serializadores número são fornecidos (confira os métodos e os métodos de extensão de ISession).Minimal string and number serializers are provided (see the methods and extension methods of ISession). Tipos complexos devem ser serializados pelo usuário por meio de outro mecanismo, como JSON.Complex types must be serialized by the user using another mechanism, such as JSON.

Adicione os seguintes métodos de extensão para definir e obter objetos serializáveis:Add the following extension methods to set and get serializable objects:

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);
    }
}

O exemplo a seguir mostra como definir e obter um objeto serializável com os métodos de extensão:The following example shows how to set and get a serializable object with the extension methods:

// Requires you add the Set and Get extension method mentioned in the topic.
if (HttpContext.Session.Get<DateTime>(SessionKeyTime) == default(DateTime))
{
    HttpContext.Session.Set<DateTime>(SessionKeyTime, currentTime);
}

TempDataTempData

ASP.NET Core expõe o Razor Pages TempData ou Controller TempData.ASP.NET Core exposes the Razor Pages TempData or Controller TempData. Essa propriedade armazena dados até que eles sejam lidos em outra solicitação.This property stores data until it's read in another request. Os métodos Keep (String) e Peek (String) podem ser usados para examinar os dados sem exclusão no final da solicitação.Keep(String) and Peek(string) methods can be used to examine the data without deletion at the end of the request. Keep () marca todos os itens no dicionário para retenção.Keep() marks all items in the dictionary for retention. TempDataé particularmente útil para o redirecionamento quando os dados são necessários para mais do que uma única solicitação.TempData is particularly useful for redirection when data is required for more than a single request. TempDataé implementado por TempData provedores usando cookies ou o estado de sessão.TempData is implemented by TempData providers using either cookies or session state.

Amostras de TempDataTempData samples

Considere a seguinte página que cria um cliente:Consider the following page that creates a customer:

public class CreateModel : PageModel
{
    private readonly RazorPagesContactsContext _context;

    public CreateModel(RazorPagesContactsContext context)
    {
        _context = context;
    }

    public IActionResult OnGet()
    {
        return Page();
    }

    [TempData]
    public string Message { get; set; }

    [BindProperty]
    public Customer Customer { get; set; }

    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }

        _context.Customer.Add(Customer);
        await _context.SaveChangesAsync();
        Message = $"Customer {Customer.Name} added";

        return RedirectToPage("./IndexPeek");
    }
}

A página a seguir TempData["Message"]exibe:The following page displays TempData["Message"]:

@page
@model IndexModel

<h1>Peek Contacts</h1>

@{
    if (TempData.Peek("Message") != null)
    {
        <h3>Message: @TempData.Peek("Message")</h3>
    }
}

@*Content removed for brevity.*@

Na marcação anterior, no final da solicitação, TempData["Message"] não é excluído porque Peek é usado.In the preceding markup, at the end of the request, TempData["Message"] is not deleted because Peek is used. A atualização da página TempData["Message"]é exibida.Refreshing the page displays TempData["Message"].

A marcação a seguir é semelhante ao código anterior, mas usa Keep para preservar os dados no final da solicitação:The following markup is similar to the preceding code, but uses Keep to preserve the data at the end of the request:

@page
@model IndexModel

<h1>Contacts Keep</h1>

@{
    if (TempData["Message"] != null)
    {
        <h3>Message: @TempData["Message"]</h3>
    }
    TempData.Keep("Message");
}

@*Content removed for brevity.*@

A navegação entre as páginas IndexPeek e IndexKeep não TempData["Message"]será excluída.Navigating between the IndexPeek and IndexKeep pages won't delete TempData["Message"].

O código a seguir TempData["Message"]exibe, mas no final da solicitação, TempData["Message"] é excluído:The following code displays TempData["Message"], but at the end of the request, TempData["Message"] is deleted:

@page
@model IndexModel

<h1>Index no Keep or Peek</h1>

@{
    if (TempData["Message"] != null)
    {
        <h3>Message: @TempData["Message"]</h3>
    }
}

@*Content removed for brevity.*@

Provedores de TempDataTempData providers

O provedor TempData baseado em cookies é usado por padrão para armazenar TempData em cookies.The cookie-based TempData provider is used by default to store TempData in cookies.

Os dados do cookie são criptografados usando IDataProtector, codificado com Base64UrlTextEncoder, em seguida, em partes.The cookie data is encrypted using IDataProtector, encoded with Base64UrlTextEncoder, then chunked. Como o cookie é dividido em partes, o limite de tamanho de cookie único encontrado no ASP.NET Core 1.x não se aplica.Because the cookie is chunked, the single cookie size limit found in ASP.NET Core 1.x doesn't apply. Os dados do cookie não são compactados porque a compactação de dados criptografados pode levar a problemas de segurança, como os ataques CRIME e BREACH.The cookie data isn't compressed because compressing encrypted data can lead to security problems such as the CRIME and BREACH attacks. Para obter mais informações sobre o provedor de TempData baseado em cookie, consulte CookieTempDataProvider.For more information on the cookie-based TempData provider, see CookieTempDataProvider.

Escolha um provedor de TempDataChoose a TempData provider

Escolher um provedor de TempData envolve várias considerações, como:Choosing a TempData provider involves several considerations, such as:

  1. O aplicativo já usa estado de sessão?Does the app already use session state? Se for o caso, usar o provedor de TempData do estado de sessão não terá custos adicionais para o aplicativo (além do tamanho dos dados).If so, using the session state TempData provider has no additional cost to the app (aside from the size of the data).
  2. O aplicativo usa TempData apenas raramente para quantidades relativamente pequenas de dados (até 500 bytes)?Does the app use TempData only sparingly for relatively small amounts of data (up to 500 bytes)? Em caso afirmativo, o provedor de TempData do cookie adiciona um pequeno custo a cada solicitação que transportar TempData.If so, the cookie TempData provider adds a small cost to each request that carries TempData. Caso contrário, o provedor de TempData do estado de sessão pode ser útil para evitar fazer viagens de ida e volta para uma grande quantidade de dados a cada solicitação até que TempData seja consumido.If not, the session state TempData provider can be beneficial to avoid round-tripping a large amount of data in each request until the TempData is consumed.
  3. O aplicativo é executado em um farm de servidores em vários servidores?Does the app run in a server farm on multiple servers? Se for o caso, não será necessária nenhuma configuração adicional para usar o provedor TempData do cookie fora da Proteção de Dados (confira Proteção de dados do ASP.NET Core e Provedores de armazenamento de chaves).If so, there's no additional configuration required to use the cookie TempData provider outside of Data Protection (see Proteção de dados do ASP.NET Core and Key storage providers).

Observação

A maioria dos clientes da Web (como navegadores da Web) impõem limites quanto ao tamanho máximo de cada cookie, o número total de cookies ou ambos.Most web clients (such as web browsers) enforce limits on the maximum size of each cookie, the total number of cookies, or both. Ao usar o provedor TempData do cookie, verifique se o aplicativo não ultrapassará esses limites.When using the cookie TempData provider, verify the app won't exceed these limits. Considere o tamanho total dos dados.Consider the total size of the data. Conta para aumento no tamanho de cookie devido à criptografia e ao agrupamento.Account for increases in cookie size due to encryption and chunking.

Configurar o provedor de TempDataConfigure the TempData provider

O provedor de TempData baseado em cookie é habilitado por padrão.The cookie-based TempData provider is enabled by default.

Para habilitar o provedor TempData baseado em sessão, use o método de extensão AddSessionStateTempDataProvider:To enable the session-based TempData provider, use the AddSessionStateTempDataProvider extension method:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
        .AddSessionStateTempDataProvider();

    services.AddSession();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();
    app.UseSession();
    app.UseMvc();
}

A ordem do middleware é importante.The order of middleware is important. No exemplo anterior, uma exceção InvalidOperationException ocorre quando UseSession é invocado após UseMvc.In the preceding example, an InvalidOperationException exception occurs when UseSession is invoked after UseMvc. Para obter mais informações, veja Ordenação de Middleware.For more information, see Middleware Ordering.

Importante

Se o alvo for o .NET Framework e o provedor TempData baseado em sessão for usado, adicione o pacote Microsoft.AspNetCore.Session ao projeto.If targeting .NET Framework and using the session-based TempData provider, add the Microsoft.AspNetCore.Session package to the project.

Cadeias de consultaQuery strings

É possível passar uma quantidade limitada de dados de uma solicitação para outra adicionando-a à cadeia de caracteres de consulta da nova solicitação.A limited amount of data can be passed from one request to another by adding it to the new request's query string. Isso é útil para capturar o estado de uma maneira persistente que permita que links com estado inserido sejam compartilhados por email ou por redes sociais.This is useful for capturing state in a persistent manner that allows links with embedded state to be shared through email or social networks. Uma vez que cadeias de consulta de URL são públicas, nunca use cadeias de consulta para dados confidenciais.Because URL query strings are public, never use query strings for sensitive data.

Além da possibilidade de ocorrência de compartilhamento não intencional, incluir dados em cadeias de consulta pode criar oportunidades para ataques de CSRF (solicitação intersite forjada), que podem enganar os usuários para que eles visitem sites mal-intencionados enquanto estão autenticados.In addition to unintended sharing, including data in query strings can create opportunities for Cross-Site Request Forgery (CSRF) attacks, which can trick users into visiting malicious sites while authenticated. Invasores então podem roubar dados do usuário do aplicativo ou executar ações mal-intencionadas em nome do usuário.Attackers can then steal user data from the app or take malicious actions on behalf of the user. Qualquer estado de sessão ou aplicativo preservado deve se proteger contra ataques CSRF.Any preserved app or session state must protect against CSRF attacks. Para obter mais informações, confira Impedir ataques de XSRF/CSRF (solicitação intersite forjada).For more information, see Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks.

Campos ocultosHidden fields

Dados podem ser salvos em campos de formulário ocultos e postados novamente na solicitação seguinte.Data can be saved in hidden form fields and posted back on the next request. Isso é comum em formulários com várias páginas.This is common in multi-page forms. Uma vez que o cliente potencialmente pode adulterar os dados, o aplicativo deve sempre revalidar os dados armazenados nos campos ocultos.Because the client can potentially tamper with the data, the app must always revalidate the data stored in hidden fields.

HttpContext.ItemsHttpContext.Items

A coleção HttpContext.Items é usada para armazenar dados durante o processamento de uma única solicitação.The HttpContext.Items collection is used to store data while processing a single request. O conteúdo da coleção é descartado após uma solicitação ser processada.The collection's contents are discarded after a request is processed. A coleção Items costuma ser usada para permitir que componentes ou middleware se comuniquem quando operam em diferentes momentos durante uma solicitação e não têm nenhuma maneira direta de passar parâmetros.The Items collection is often used to allow components or middleware to communicate when they operate at different points in time during a request and have no direct way to pass parameters.

No exemplo a seguir, middleware adiciona isVerified à coleção Items.In the following example, middleware adds isVerified to the Items collection.

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

Mais tarde no pipeline, outro middleware poderá acessar o valor de isVerified:Later in the pipeline, another middleware can access the value of isVerified:

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

Para middleware usado apenas por um único aplicativo, chaves string são aceitáveis.For middleware that's only used by a single app, string keys are acceptable. Middleware compartilhado entre instâncias do aplicativo deve usar chaves de objeto únicas para evitar colisões de chaves.Middleware shared between app instances should use unique object keys to avoid key collisions. O exemplo a seguir mostra como usar uma chave de objeto exclusiva definida em uma classe de middleware:The following example shows how to use a unique object key defined in a middleware class:

public class HttpContextItemsMiddleware
{
    private readonly RequestDelegate _next;
    public static readonly object HttpContextItemsMiddlewareKey = new Object();

    public HttpContextItemsMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        httpContext.Items[HttpContextItemsMiddlewareKey] = "K-9";

        await _next(httpContext);
    }
}

public static class HttpContextItemsMiddlewareExtensions
{
    public static IApplicationBuilder 
        UseHttpContextItemsMiddleware(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<HttpContextItemsMiddleware>();
    }
}

Outros códigos podem acessar o valor armazenado em HttpContext.Items usando a chave exposta pela classe do middleware:Other code can access the value stored in HttpContext.Items using the key exposed by the middleware class:

HttpContext.Items
    .TryGetValue(HttpContextItemsMiddleware.HttpContextItemsMiddlewareKey, 
        out var middlewareSetValue);
SessionInfo_MiddlewareValue = 
    middlewareSetValue?.ToString() ?? "Middleware value not set!";

Essa abordagem também tem a vantagem de eliminar o uso de cadeias de caracteres de chave no código.This approach also has the advantage of eliminating the use of key strings in the code.

CacheCache

O cache é uma maneira eficiente de armazenar e recuperar dados.Caching is an efficient way to store and retrieve data. O aplicativo pode controlar o tempo de vida de itens em cache.The app can control the lifetime of cached items.

Dados armazenados em cache não são associados uma solicitação, usuário ou sessão específico.Cached data isn't associated with a specific request, user, or session. Tenha cuidado para não armazenar em cache dados específicos do usuário que podem ser recuperados pelas solicitações de outros usuários.Be careful not to cache user-specific data that may be retrieved by other users' requests.

Para obter mais informações, consulte Cache de resposta no ASP.NET Core.For more information, see Cache de resposta no ASP.NET Core.

Injeção de dependênciaDependency Injection

Use a Injeção de dependência para disponibilizar dados para todos os usuários:Use Dependency Injection to make data available to all users:

  1. Defina um serviço que contenha os dados.Define a service containing the data. Por exemplo, uma classe denominada MyAppData está definida:For example, a class named MyAppData is defined:

    public class MyAppData
    {
        // Declare properties and methods
    }
    
  2. Adicione a classe de serviço a Startup.ConfigureServices:Add the service class to Startup.ConfigureServices:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<MyAppData>();
    }
    
  3. Consuma a classe de serviço de dados:Consume the data service class:

    public class IndexModel : PageModel
    {
        public IndexModel(MyAppData myService)
        {
            // Do something with the service
            //    Examples: Read data, store in a field or property
        }
    }
    

Erros comunsCommon errors

  • "Não é possível resolver o serviço para o tipo 'Microsoft.Extensions.Caching.Distributed.IDistributedCache' ao tentar ativar 'Microsoft.AspNetCore.Session.DistributedSessionStore'.""Unable to resolve service for type 'Microsoft.Extensions.Caching.Distributed.IDistributedCache' while attempting to activate 'Microsoft.AspNetCore.Session.DistributedSessionStore'."

    Geralmente, isso é causado quando não é configurada pelo menos uma implementação de IDistributedCache.This is usually caused by failing to configure at least one IDistributedCache implementation. Para obter mais informações, consulte Caching distribuído no ASP.NET Core e Cache na memória no ASP.NET Core.For more information, see Caching distribuído no ASP.NET Core and Cache na memória no ASP.NET Core.

  • Caso a sessão de middleware não consiga manter uma sessão (por exemplo, se o repositório de backup não estiver disponível), o middleware registrará a exceção e a solicitação continuará normalmente.In the event that the session middleware fails to persist a session (for example, if the backing store isn't available), the middleware logs the exception and the request continues normally. Isso leva a um comportamento imprevisível.This leads to unpredictable behavior.

    Por exemplo, um usuário armazena um carrinho de compras na sessão.For example, a user stores a shopping cart in session. O usuário adiciona um item ao carrinho, mas a confirmação falha.The user adds an item to the cart but the commit fails. O aplicativo não sabe sobre a falha, assim, relata ao usuário que o item foi adicionado ao seu carrinho, o que não é verdade.The app doesn't know about the failure so it reports to the user that the item was added to their cart, which isn't true.

    A abordagem recomendada para verificar se há erros é chamar await feature.Session.CommitAsync(); do código de aplicativo quando o aplicativo tiver terminado de gravar na sessão.The recommended approach to check for errors is to call await feature.Session.CommitAsync(); from app code when the app is done writing to the session. CommitAsync gerará uma exceção se o repositório de backup não estiver disponível.CommitAsync throws an exception if the backing store is unavailable. Se CommitAsync falhar, o aplicativo poderá processar a exceção.If CommitAsync fails, the app can process the exception. LoadAsync gera sob as mesmas condições em que o armazenamento de dados não está disponível.LoadAsync throws under the same conditions where the data store is unavailable.

Sinalizador e estado da sessãoSignalR and session state

Os aplicativos signalr não devem usar o estado de sessão para armazenar informações.SignalR apps should not use session state to store information. Os aplicativos signalr podem armazenar por estado de Context.Items conexão no no Hub.SignalR apps can store per connection state in Context.Items in the hub.

Recursos adicionaisAdditional resources

Hospedar o ASP.NET Core em um web farm