Správa relací a stavu v ASP.NET Core

Rick Anderson, Kirk Larkin a Diana LaRose

HTTP je bezstavový protokol. Ve výchozím nastavení jsou požadavky HTTP nezávislé zprávy, které nezachovají uživatelské hodnoty. Tento článek popisuje několik přístupů k zachování uživatelských dat mezi požadavky.

Správa stavu

Stav lze uložit pomocí několika přístupů. Každý přístup je popsaný dále v tomto článku.

Přístup k úložišti Mechanismus úložiště
Cookies HTTP cookies. Může obsahovat data uložená pomocí kódu aplikace na straně serveru.
Stav relace Kód aplikace na straně serveru a HTTP cookie
TempData Stav HTTP cookies nebo relace
Řetězce dotazů Řetězce dotazů HTTP
Skrytá pole Pole formuláře HTTP
HttpContext.Items Kód aplikace na straně serveru
Cache Kód aplikace na straně serveru

SignalR/Blazor Server a správa stavu na základě kontextu HTTP

SignalR aplikace by neměly používat stav relace a další přístupy ke správě stavu, které při ukládání informací spoléhají na stabilní kontext HTTP. SignalR aplikace můžou ukládat stav jednotlivých připojení v Context.Items centru. Další informace a alternativní přístupy ke správě stavu pro Blazor Server aplikace najdete v tématu ASP.NET Blazor Základní správa stavu.

CookieS

Cookieukládá data napříč požadavky. Vzhledem k tomu cookie, že se odesílají s každou žádostí, měla by být jejich velikost zachována na minimum. V ideálním případě by měl být uložen cookie pouze identifikátor s daty uloženými aplikací. Většina prohlížečů omezuje cookie velikost na 4096 bajtů. Pro každou doménu je k dispozici pouze omezený počet cookies.

Vzhledem k tomu cookie, že se na ně vztahuje manipulace, musí je aplikace ověřit. Cookieuživatele je možné odstranit a vyprší jejich platnost u klientů. Obecně cookiejsou však nejodolnější formou trvalosti dat v klientovi.

CookieČasto se používají k přizpůsobení, kde je obsah přizpůsobený známému uživateli. Uživatel je identifikován pouze a ve většině případů se neověřuje. Může cookie uložit jméno uživatele, název účtu nebo jedinečné ID uživatele, například IDENTIFIKÁTOR GUID. Dá cookie se použít pro přístup k individuálnímu nastavení uživatele, jako je například upřednostňovaná barva pozadí webu.

Při vydávání cookiea řešení problémů s ochranou osobních údajů se podívejte na obecné nařízení Evropské unie o ochraně osobních údajů (GDPR). Další informace najdete v tématu Obecná podpora nařízení o ochraně osobních údajů (GDPR) v ASP.NET Core.

Stav relace

Stav relace je scénář ASP.NET Core pro ukládání uživatelských dat, zatímco uživatel prochází webovou aplikaci. Stav relace používá úložiště spravované aplikací k zachování dat napříč požadavky z klienta. Data relace jsou podporována mezipamětí a považují se za dočasné data. Web by měl dál fungovat bez dat relace. Důležitá data aplikace by měla být uložená v uživatelské databázi a uložená v mezipaměti v relaci pouze jako optimalizace výkonu.

Relace není v SignalR aplikacích podporovaná, protože SignalR centrum může spouštět nezávisle na kontextu HTTP. K tomu může dojít například v případě, že je dlouhý požadavek na dotazování otevřený centrem nad rámec životnosti kontextu HTTP požadavku.

ASP.NET Core udržuje stav relace poskytnutím cookie klientovi, který obsahuje ID relace. cookie ID relace:

  • Odešle se do aplikace s každou žádostí.
  • Aplikace je používána k načtení dat relace.

Stav relace vykazuje následující chování:

  • Relace cookie je specifická pro prohlížeč. Relace se nesdílejí napříč prohlížeči.
  • Relace cookiese odstraní, když relace prohlížeče skončí.
  • cookie Pokud je přijata pro relaci s vypršenou platností, vytvoří se nová relace, která používá stejnou relaci cookie.
  • Prázdné relace se nezachovají. Relace musí mít nastavenou alespoň jednu hodnotu, aby se relace zachovala napříč požadavky. Pokud se relace nezachová, vygeneruje se nové ID relace pro každý nový požadavek.
  • Aplikace uchovává relaci po omezenou dobu po poslední žádosti. Aplikace buď nastaví časový limit relace, nebo použije výchozí hodnotu 20 minut. Stav relace je ideální pro ukládání uživatelských dat:
    • To je specifické pro konkrétní relaci.
    • Pokud data nevyžadují trvalé úložiště napříč relacemi.
  • Data relace se odstraní buď při ISession.Clear zavolání implementace, nebo při vypršení platnosti relace.
  • Neexistuje žádný výchozí mechanismus, který by informoval kód aplikace, že byl klientský prohlížeč zavřený nebo když je relace cookie odstraněna nebo vypršela jeho platnost.
  • Stav cookierelace není ve výchozím nastavení označený jako nezbytný. Stav relace není funkční, pokud není sledování povoleno návštěvníkem webu. Další informace najdete v tématu Obecná podpora nařízení o ochraně osobních údajů (GDPR) v ASP.NET Core.
  • Poznámka: Z rozhraní ASP.NET Framework není žádná náhrada za cookieméně funkcí relace, protože je považována za nezabezpečená a může vést k útokům na opravu relací.

Upozorňující

Neukládejte citlivá data ve stavu relace. Uživatel nemusí zavřít prohlížeč a vymazat relaci cookie. Některé prohlížeče udržují platné relace cookienapříč okny prohlížeče. Relace nemusí být omezena na jednoho uživatele. Další uživatel může pokračovat v procházení aplikace se stejnou relací cookie.

Zprostředkovatel mezipaměti v paměti ukládá data relace do paměti serveru, kde se nachází aplikace. Ve scénáři serverové farmy:

  • Pomocí rychlých relací můžete každou relaci svázat s konkrétní instancí aplikace na jednotlivém serveru. Aplikace Azure Služba používá směrování žádostí aplikace (ARR) k vynucování rychlých relací ve výchozím nastavení. Rychlé relace ale můžou ovlivnit škálovatelnost a komplikují aktualizace webových aplikací. Lepším přístupem je použít distribuovanou mezipaměť Redis nebo SQL Server, která nevyžaduje rychlé relace. Další informace naleznete v tématu Distribuované ukládání do mezipaměti v ASP.NET Core.
  • Relace cookie je šifrovaná prostřednictvím IDataProtector. Ochrana dat musí být správně nakonfigurovaná tak, aby na každém počítači četla relace cookie. Další informace najdete v tématu ASP.NET Přehled základní ochrany dat a poskytovatelé úložiště klíčů.

Konfigurace stavu relace

Middleware pro správu stavu relace je součástí architektury. Pokud chcete povolit middleware relace, Program.cs musí obsahovat:

Následující kód ukazuje, jak nastavit zprostředkovatele relace v paměti s výchozí implementací IDistributedCachev paměti:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

builder.Services.AddDistributedMemoryCache();

builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromSeconds(10);
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.UseSession();

app.MapRazorPages();
app.MapDefaultControllerRoute();

app.Run();

Předchozí kód nastaví krátký časový limit pro zjednodušení testování.

Pořadí middlewaru je důležité. Zavolat UseSession po UseRouting a před MapRazorPages a MapDefaultControllerRoute . Viz Řazení middlewaru.

HttpContext.Session je k dispozici po nakonfigurování stavu relace.

HttpContext.Session není možné získat přístup před UseSession zavolání.

Po zahájení zápisu aplikace do streamu odpovědí nejde vytvořit novou relaci s novou relací cookie . Výjimka se zaznamená v protokolu webového serveru a nezobrazí se v prohlížeči.

Asynchronní načtení stavu relace

Výchozí zprostředkovatel relace v ASP.NET Core načte záznamy relace ze základního IDistributedCache záložního úložiště asynchronně pouze v případě, že ISession.LoadAsync metoda je explicitně volána před TryGetValue, Setnebo Remove metody. Pokud LoadAsync není volána jako první, základní záznam relace se načte synchronně, což může mít za následek snížení výkonu ve velkém měřítku.

Chcete-li, aby aplikace vynucovaly tento vzor, zabalte DistributedSessionStore a DistributedSession implementace s verzemi, které vyvolá výjimku, pokud LoadAsync metoda není volána před TryGetValue, Setnebo Remove. Zaregistrujte zabalené verze v kontejneru služeb.

Možnosti relace

Chcete-li přepsat výchozí hodnoty relace, použijte SessionOptions.

Možnost Popis
Cookie Určuje nastavení použitá k vytvoření cookiesouboru . Name výchozí hodnota je SessionDefaults.CookieName (.AspNetCore.Session). Path výchozí hodnota je SessionDefaults.CookiePath (/). SameSite výchozí hodnota je SameSiteMode.Lax (1). Výchozí hodnotou HttpOnly je true. Výchozí hodnotou IsEssential je false.
IdleTimeout Určuje IdleTimeout , jak dlouho může být relace nečinná, než se její obsah opustí. Každý přístup k relaci resetuje časový limit. Toto nastavení se vztahuje pouze na obsah relace, nikoli na cookie. Výchozí nastavení je 20 minut.
IOTimeout Maximální doba, po kterou je možné načíst relaci z úložiště nebo ji potvrdit zpět do úložiště. Toto nastavení se může vztahovat pouze na asynchronní operace. Tento časový limit lze zakázat pomocí InfiniteTimeSpan. Výchozí hodnota je 1 minuta.

Relace používá cookie ke sledování a identifikaci požadavků z jednoho prohlížeče. Ve výchozím nastavení se tento cookie název .AspNetCore.Sessionpoužívá a používá cestu /. cookie Vzhledem k tomu, že výchozí nastavení neurčuje doménu, není pro skript na straně klienta na stránce k dispozici (protože HttpOnly výchozí hodnota je true).

Chcete-li přepsat cookie výchozí hodnoty relace, použijte SessionOptions:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

builder.Services.AddDistributedMemoryCache();

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

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.UseSession();

app.MapRazorPages();
app.MapDefaultControllerRoute();

app.Run();

Aplikace pomocí IdleTimeout vlastnosti určuje, jak dlouho může být relace nečinná, než se její obsah v mezipaměti serveru opustí. Tato vlastnost je nezávislá na cookie vypršení platnosti. Každý požadavek, který prochází middlewarem relace, resetuje časový limit.

Stav relace není uzamčený. Pokud se dva požadavky současně pokusí upravit obsah relace, poslední požadavek přepíše první. Session je implementováno jako koherentní relace, což znamená, že veškerý obsah je uložen společně. Když se dva požadavky snaží upravit různé hodnoty relace, může poslední požadavek přepsat změny relace provedené prvním.

Nastavení a získání hodnot relace

Stav relace je přístupný z Razor třídy Pages PageModel nebo třídy MVC Controller s HttpContext.Session. Tato vlastnost je ISession implementace.

Implementace ISession poskytuje několik rozšiřujících metod pro nastavení a načtení celočíselné a řetězcové hodnoty. Metody rozšíření jsou v Microsoft.AspNetCore.Http oboru názvů.

ISession rozšiřující metody:

Následující příklad načte hodnotu relace pro IndexModel.SessionKeyName klíč (_Name v ukázkové aplikaci) na Razor stránce Pages:

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

...

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

Následující příklad ukazuje, jak nastavit a získat celé číslo a řetězec:

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

    private readonly ILogger<IndexModel> _logger;

    public IndexModel(ILogger<IndexModel> logger)
    {
        _logger = logger;
    }

    public void OnGet()
    {
        if (string.IsNullOrEmpty(HttpContext.Session.GetString(SessionKeyName)))
        {
            HttpContext.Session.SetString(SessionKeyName, "The Doctor");
            HttpContext.Session.SetInt32(SessionKeyAge, 73);
        }
        var name = HttpContext.Session.GetString(SessionKeyName);
        var age = HttpContext.Session.GetInt32(SessionKeyAge).ToString();

        _logger.LogInformation("Session Name: {Name}", name);
        _logger.LogInformation("Session Age: {Age}", age);
    }
}

Následující kód zobrazí hodnoty relace na Razor stránce:

@page
@model PrivacyModel
@{
    ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>

<div class="text-center">
<p><b>Name:</b> @HttpContext.Session.GetString("_Name");<b>Age:

</b> @HttpContext.Session.GetInt32("_Age").ToString()</p>
</div>


Všechna data relace musí být serializována, aby bylo možné povolit scénář distribuované mezipaměti, i když používáte mezipaměť v paměti. Řetězcové a celočíselné serializátory jsou poskytovány rozšiřujícími metodami ISession. Komplexní typy musí být serializovány uživatelem pomocí jiného mechanismu, například JSON.

K serializaciobjektůch

public static class SessionExtensions
{
    public static void Set<T>(this ISession session, string key, T value)
    {
        session.SetString(key, JsonSerializer.Serialize(value));
    }

    public static T? Get<T>(this ISession session, string key)
    {
        var value = session.GetString(key);
        return value == null ? default : JsonSerializer.Deserialize<T>(value);
    }
}

Následující příklad ukazuje, jak nastavit a získat serializovatelný objekt s SessionExtensions třídou:

using Microsoft.AspNetCore.Mvc.RazorPages;
using Web.Extensions;    // SessionExtensions

namespace SessionSample.Pages
{
    public class Index6Model : PageModel
    {
        const string SessionKeyTime = "_Time";
        public string? SessionInfo_SessionTime { get; private set; }
        private readonly ILogger<Index6Model> _logger;

        public Index6Model(ILogger<Index6Model> logger)
        {
            _logger = logger;
        }

        public void OnGet()
        {
            var currentTime = DateTime.Now;

            // Requires SessionExtensions from sample.
            if (HttpContext.Session.Get<DateTime>(SessionKeyTime) == default)
            {
                HttpContext.Session.Set<DateTime>(SessionKeyTime, currentTime);
            }
            _logger.LogInformation("Current Time: {Time}", currentTime);
            _logger.LogInformation("Session Time: {Time}", 
                           HttpContext.Session.Get<DateTime>(SessionKeyTime));

        }
    }
}

Upozorňující

Uložení živého objektu v relaci by se mělo používat s opatrností, protože u serializovaných objektů může dojít k mnoha problémům. Další informace najdete v tématu Relace, které by měly umožňovat ukládání objektů (dotnet/aspnetcore #18159).

TempData

ASP.NET Core zpřístupňuje stránky tempdata nebo kontroleru TempData.Razor Tato vlastnost ukládá data, dokud se nepřečte v jiném požadavku. Metody Keep(String) a Peek(string) lze použít k prozkoumání dat bez odstranění na konci požadavku. Zachovejte značky všech položek ve slovníku pro uchovávání informací. TempData Je:

  • Užitečné pro přesměrování v případě, že se data vyžadují pro více než jeden požadavek.
  • Implementují TempData poskytovatelé pomocí stavu cookierelace nebo s.

Ukázky tempData

Představte si následující stránku, která vytvoří zákazníka:

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

Zobrazí se následující stránka TempData["Message"]:

@page
@model IndexModel

<h1>Peek Contacts</h1>

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

@*Content removed for brevity.*@

V předchozím kódu se na konci požadavku neodstraní, TempData["Message"]protože Peek se používá. Při aktualizaci stránky se zobrazí obsah souboru TempData["Message"].

Následující kód je podobný předchozímu kódu, ale používá Keep se k zachování dat na konci požadavku:

@page
@model IndexModel

<h1>Contacts Keep</h1>

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

@*Content removed for brevity.*@

Přechod mezi stránkami IndexPeek a IndexKeep se neodstraní TempData["Message"].

Následující kód se zobrazí TempData["Message"], ale na konci požadavku TempData["Message"] se odstraní:

@page
@model IndexModel

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

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

@*Content removed for brevity.*@

Zprostředkovatelé tempData

cookieZprostředkovatel TempData založený na databázi TempData se ve výchozím nastavení používá k ukládání tempData v scookie.

Data cookie se šifrují pomocí IDataProtectorzakódovaných Base64UrlTextEncoderdat a potom se zakódují. Maximální cookie velikost je menší než 4096 bajtů kvůli šifrování a bloků dat. Data cookie nejsou komprimovaná, protože komprese šifrovaných dat může vést k problémům se zabezpečením, jako jsou útoky CRIME a BREACH útoky. Další informace o poskytovateli tempdata založeném cookiena technologii TempData naleznete v tématu CookieTempDataProvider.

Volba zprostředkovatele TempData

Volba zprostředkovatele TempData zahrnuje několik aspektů, například:

  • Používá aplikace už stav relace? Pokud ano, použití poskytovatele TempData stavu relace nemá žádné další náklady na aplikaci nad rámec velikosti dat.
  • Používá aplikace tempData jen střídmě pro relativně malé objemy dat, až 500 bajtů? Pokud ano, cookie poskytovatel TempData přidá malé náklady na každý požadavek, který nese TempData. Pokud tomu tak není, může být poskytovatel tempData stavu relace výhodný, aby se zabránilo zaokrouhlení velkého množství dat v každém požadavku, dokud se tempData nespotřebuje.
  • Běží aplikace v serverové farmě na více serverech? Pokud ano, není nutná žádná další konfigurace pro použití cookie zprostředkovatele TempData mimo ochranu dat. Další informace najdete v tématu ASP.NET Přehled základní ochrany dat a poskytovatelé úložiště klíčů.

Většina webových klientů, jako jsou webové prohlížeče, vynucuje omezení maximální velikosti každého cookie a celkového počtu cookies. Při použití cookie zprostředkovatele TempData ověřte, že aplikace tyto limity nepřekročí. Zvažte celkovou velikost dat. Účet se zvětší cookie kvůli šifrování a bloků dat.

Konfigurace zprostředkovatele TempData

Poskytovatel cookieTempData založený na technologii TempData je ve výchozím nastavení povolený.

Pokud chcete povolit zprostředkovatele TempData založeného na relaci, použijte metodu AddSessionStateTempDataProvider rozšíření. Vyžaduje se AddSessionStateTempDataProvider pouze jedno volání:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages()
                    .AddSessionStateTempDataProvider();
builder.Services.AddControllersWithViews()
                    .AddSessionStateTempDataProvider();

builder.Services.AddSession();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.UseSession();

app.MapRazorPages();
app.MapDefaultControllerRoute();

app.Run();

Řetězce dotazů

Omezené množství dat je možné předat z jednoho požadavku do jiného přidáním do řetězce dotazu nového požadavku. To je užitečné pro trvalé zachycení stavu, které umožňuje sdílení propojení s vloženým stavem prostřednictvím e-mailu nebo sociálních sítí. Protože řetězce dotazu ADRESY URL jsou veřejné, nikdy nepoužívejte řetězce dotazů pro citlivá data.

Kromě nezamýšleného sdílení, včetně dat v řetězcích dotazů, může aplikace vystavit útokům CSRF (Cross-Site Request Forgery). Všechny zachované stavy relace musí chránit před útoky CSRF. Další informace najdete v tématu Prevence útoků založených na padělání žádosti posílané mezi weby (XSRF/CSRF) v ASP.NET Core.

Skrytá pole

Data lze uložit do skrytých polí formuláře a publikovat zpět na další požadavek. To je běžné ve vícestrákových formulářích. Vzhledem k tomu, že klient může potenciálně manipulovat s daty, musí aplikace vždy znovu obnovit data uložená ve skrytých polích.

HttpContext.Items

Kolekce HttpContext.Items se používá k ukládání dat při zpracování jednoho požadavku. Obsah kolekce se po zpracování požadavku zahodí. Kolekce Items se často používá k tomu, aby komponenty nebo middleware komunikovaly, když během požadavku pracují v různých bodech v čase a nemají přímý způsob předávání parametrů.

V následujícím příkladu middleware přidá isVerified do Items kolekce:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

ILogger logger = app.Logger;

app.Use(async (context, next) =>
{
    // context.Items["isVerified"] is null
    logger.LogInformation($"Before setting: Verified: {context.Items["isVerified"]}");
    context.Items["isVerified"] = true;
    await next.Invoke();
});

app.Use(async (context, next) =>
{
    // context.Items["isVerified"] is true
    logger.LogInformation($"Next: Verified: {context.Items["isVerified"]}");
    await next.Invoke();
});

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

app.Run();

U middlewaru, který se používá jenom v jedné aplikaci, je nepravděpodobné, že použití pevného string klíče způsobí kolizi klíče. Aby se však zabránilo úplné kolizi klíče, object lze ji použít jako klíč položky. Tento přístup je zvláště užitečný pro middleware, který se sdílí mezi aplikacemi, a má také výhodu odstranění použití klíčových řetězců v kódu. Následující příklad ukazuje, jak použít object klíč definovaný v middlewarové třídě:

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

    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 app)
    {
        return app.UseMiddleware<HttpContextItemsMiddleware>();
    }
}

Jiný kód má přístup k hodnotě uložené v HttpContext.Items klíči vystavené middlewarovou třídou:

public class Index2Model : PageModel
{
    private readonly ILogger<Index2Model> _logger;

    public Index2Model(ILogger<Index2Model> logger)
    {
        _logger = logger;
    }

    public void OnGet()
    {
        HttpContext.Items
            .TryGetValue(HttpContextItemsMiddleware.HttpContextItemsMiddlewareKey,
                out var middlewareSetValue);

        _logger.LogInformation("Middleware value {MV}",
            middlewareSetValue?.ToString() ?? "Middleware value not set!");
    }
}

Cache

Ukládání do mezipaměti je efektivní způsob, jak ukládat a načítat data. Aplikace může řídit životnost položek uložených v mezipaměti. Další informace najdete v tématu Ukládání odpovědí do mezipaměti v ASP.NET Core.

Data uložená v mezipaměti nejsou přidružená ke konkrétnímu požadavku, uživateli nebo relaci. Neukádejte data specifická pro uživatele, která mohou být načtena jinými požadavky uživatelů.

Pokud chcete ukládat data do mezipaměti pro celou aplikaci, přečtěte si téma Mezipaměť v paměti v ASP.NET Core.

Kontrola stavu relace

ISession.IsAvailable je určen ke kontrole přechodných selhání. Volání IsAvailable před spuštěním middlewaru relace vyvolá výjimku InvalidOperationException.

Knihovny, které potřebují otestovat dostupnost relace, mohou používat HttpContext.Features.Get<ISessionFeature>()?.Session != null.

Běžné chyby

Pokud se middleware relace nepodaří zachovat relaci:

  • Middleware zaznamená výjimku a požadavek pokračuje normálně.
  • To vede k nepředvídatelným chováním.

Middleware relace nemůže zachovat relaci, pokud záložní úložiště není k dispozici. Uživatel například ukládá nákupní košík v relaci. Uživatel přidá položku do košíku, ale potvrzení se nezdaří. Aplikace o chybě neví, takže hlásí uživateli, že byla položka přidána do košíku, což není pravda.

Doporučeným přístupem ke kontrole chyb je volání await feature.Session.CommitAsync při zápisu aplikace do relace. CommitAsync vyvolá výjimku, pokud záložní úložiště není k dispozici. Pokud CommitAsync selže, aplikace může výjimku zpracovat. LoadAsync vyvolá za stejných podmínek, pokud úložiště dat není k dispozici.

Další materiály

Zobrazení nebo stažení ukázkového kódu (postup stažení)

Hostování ASP.NET Core ve webové farmě

Rick Anderson, Kirk Larkin a Diana LaRose

HTTP je bezstavový protokol. Ve výchozím nastavení jsou požadavky HTTP nezávislé zprávy, které nezachovají uživatelské hodnoty. Tento článek popisuje několik přístupů k zachování uživatelských dat mezi požadavky.

Zobrazení nebo stažení ukázkového kódu (postup stažení)

Správa stavu

Stav lze uložit pomocí několika přístupů. Každý přístup je popsaný dále v tomto článku.

Přístup k úložišti Mechanismus úložiště
Cookies HTTP cookies. Může obsahovat data uložená pomocí kódu aplikace na straně serveru.
Stav relace Kód aplikace na straně serveru a HTTP cookie
TempData Stav HTTP cookies nebo relace
Řetězce dotazů Řetězce dotazů HTTP
Skrytá pole Pole formuláře HTTP
HttpContext.Items Kód aplikace na straně serveru
Cache Kód aplikace na straně serveru

SignalR/Blazor Server a správa stavu na základě kontextu HTTP

SignalR aplikace by neměly používat stav relace a další přístupy ke správě stavu, které při ukládání informací spoléhají na stabilní kontext HTTP. SignalR aplikace můžou ukládat stav jednotlivých připojení v Context.Items centru. Další informace a alternativní přístupy ke správě stavu pro Blazor Server aplikace najdete v tématu ASP.NET Blazor Základní správa stavu.

CookieS

Cookieukládá data napříč požadavky. Vzhledem k tomu cookie, že se odesílají s každou žádostí, měla by být jejich velikost zachována na minimum. V ideálním případě by měl být uložen cookie pouze identifikátor s daty uloženými aplikací. Většina prohlížečů omezuje cookie velikost na 4096 bajtů. Pro každou doménu je k dispozici pouze omezený počet cookies.

Vzhledem k tomu cookie, že se na ně vztahuje manipulace, musí je aplikace ověřit. Cookieuživatele je možné odstranit a vyprší jejich platnost u klientů. Obecně cookiejsou však nejodolnější formou trvalosti dat v klientovi.

CookieČasto se používají k přizpůsobení, kde je obsah přizpůsobený známému uživateli. Uživatel je identifikován pouze a ve většině případů se neověřuje. Může cookie uložit jméno uživatele, název účtu nebo jedinečné ID uživatele, například IDENTIFIKÁTOR GUID. Dá cookie se použít pro přístup k individuálnímu nastavení uživatele, jako je například upřednostňovaná barva pozadí webu.

Při vydávání cookiea řešení problémů s ochranou osobních údajů se podívejte na obecné nařízení Evropské unie o ochraně osobních údajů (GDPR). Další informace najdete v tématu Obecná podpora nařízení o ochraně osobních údajů (GDPR) v ASP.NET Core.

Stav relace

Stav relace je scénář ASP.NET Core pro ukládání uživatelských dat, zatímco uživatel prochází webovou aplikaci. Stav relace používá úložiště spravované aplikací k zachování dat napříč požadavky z klienta. Data relace jsou podporována mezipamětí a považují se za dočasné data. Web by měl dál fungovat bez dat relace. Důležitá data aplikace by měla být uložená v uživatelské databázi a uložená v mezipaměti v relaci pouze jako optimalizace výkonu.

Relace není v SignalR aplikacích podporovaná, protože SignalR centrum může spouštět nezávisle na kontextu HTTP. K tomu může dojít například v případě, že je dlouhý požadavek na dotazování otevřený centrem nad rámec životnosti kontextu HTTP požadavku.

ASP.NET Core udržuje stav relace poskytnutím cookie klientovi, který obsahuje ID relace. cookie ID relace:

  • Odešle se do aplikace s každou žádostí.
  • Aplikace je používána k načtení dat relace.

Stav relace vykazuje následující chování:

  • Relace cookie je specifická pro prohlížeč. Relace se nesdílejí napříč prohlížeči.
  • Relace cookiese odstraní, když relace prohlížeče skončí.
  • cookie Pokud je přijata pro relaci s vypršenou platností, vytvoří se nová relace, která používá stejnou relaci cookie.
  • Prázdné relace se nezachovají. Relace musí mít nastavenou alespoň jednu hodnotu, aby se relace zachovala napříč požadavky. Pokud se relace nezachová, vygeneruje se nové ID relace pro každý nový požadavek.
  • Aplikace uchovává relaci po omezenou dobu po poslední žádosti. Aplikace buď nastaví časový limit relace, nebo použije výchozí hodnotu 20 minut. Stav relace je ideální pro ukládání uživatelských dat:
    • To je specifické pro konkrétní relaci.
    • Pokud data nevyžadují trvalé úložiště napříč relacemi.
  • Data relace se odstraní buď při ISession.Clear zavolání implementace, nebo při vypršení platnosti relace.
  • Neexistuje žádný výchozí mechanismus, který by informoval kód aplikace, že byl klientský prohlížeč zavřený nebo když je relace cookie odstraněna nebo vypršela jeho platnost.
  • Stav cookierelace není ve výchozím nastavení označený jako nezbytný. Stav relace není funkční, pokud není sledování povoleno návštěvníkem webu. Další informace najdete v tématu Obecná podpora nařízení o ochraně osobních údajů (GDPR) v ASP.NET Core.

Upozorňující

Neukládejte citlivá data ve stavu relace. Uživatel nemusí zavřít prohlížeč a vymazat relaci cookie. Některé prohlížeče udržují platné relace cookienapříč okny prohlížeče. Relace nemusí být omezena na jednoho uživatele. Další uživatel může pokračovat v procházení aplikace se stejnou relací cookie.

Zprostředkovatel mezipaměti v paměti ukládá data relace do paměti serveru, kde se nachází aplikace. Ve scénáři serverové farmy:

  • Pomocí rychlých relací můžete každou relaci svázat s konkrétní instancí aplikace na jednotlivém serveru. Aplikace Azure Služba používá směrování žádostí aplikace (ARR) k vynucování rychlých relací ve výchozím nastavení. Rychlé relace ale můžou ovlivnit škálovatelnost a komplikují aktualizace webových aplikací. Lepším přístupem je použít distribuovanou mezipaměť Redis nebo SQL Server, která nevyžaduje rychlé relace. Další informace naleznete v tématu Distribuované ukládání do mezipaměti v ASP.NET Core.
  • Relace cookie je šifrovaná prostřednictvím IDataProtector. Ochrana dat musí být správně nakonfigurovaná tak, aby na každém počítači četla relace cookie. Další informace najdete v tématu ASP.NET Přehled základní ochrany dat a poskytovatelé úložiště klíčů.

Konfigurace stavu relace

Balíček Microsoft.AspNetCore.Session :

  • Architektura je zahrnuta implicitně.
  • Poskytuje middleware pro správu stavu relace.

Pokud chcete povolit middleware relace, Startup musí obsahovat:

Následující kód ukazuje, jak nastavit zprostředkovatele relace v paměti s výchozí implementací IDistributedCachev paměti:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

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

        services.AddSession(options =>
        {
            options.IdleTimeout = TimeSpan.FromSeconds(10);
            options.Cookie.HttpOnly = true;
            options.Cookie.IsEssential = true;
        });

        services.AddControllersWithViews();
        services.AddRazorPages();
    }

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

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseSession();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
            endpoints.MapRazorPages();
        });
    }
}

Předchozí kód nastaví krátký časový limit pro zjednodušení testování.

Pořadí middlewaru je důležité. Zavolat UseSession po UseRouting a před UseEndpoints. Viz Řazení middlewaru.

HttpContext.Session je k dispozici po nakonfigurování stavu relace.

HttpContext.Session není možné získat přístup před UseSession zavolání.

Po zahájení zápisu aplikace do streamu odpovědí nejde vytvořit novou relaci s novou relací cookie . Výjimka se zaznamená v protokolu webového serveru a nezobrazí se v prohlížeči.

Asynchronní načtení stavu relace

Výchozí zprostředkovatel relace v ASP.NET Core načte záznamy relace ze základního IDistributedCache záložního úložiště asynchronně pouze v případě, že ISession.LoadAsync metoda je explicitně volána před TryGetValue, Setnebo Remove metody. Pokud LoadAsync není volána jako první, základní záznam relace se načte synchronně, což může mít za následek snížení výkonu ve velkém měřítku.

Chcete-li, aby aplikace vynucovaly tento vzor, zabalte DistributedSessionStore a DistributedSession implementace s verzemi, které vyvolá výjimku, pokud LoadAsync metoda není volána před TryGetValue, Setnebo Remove. Zaregistrujte zabalené verze v kontejneru služeb.

Možnosti relace

Chcete-li přepsat výchozí hodnoty relace, použijte SessionOptions.

Možnost Popis
Cookie Určuje nastavení použitá k vytvoření cookiesouboru . Name výchozí hodnota je SessionDefaults.CookieName (.AspNetCore.Session). Path výchozí hodnota je SessionDefaults.CookiePath (/). SameSite výchozí hodnota je SameSiteMode.Lax (1). Výchozí hodnotou HttpOnly je true. Výchozí hodnotou IsEssential je false.
IdleTimeout Určuje IdleTimeout , jak dlouho může být relace nečinná, než se její obsah opustí. Každý přístup k relaci resetuje časový limit. Toto nastavení se vztahuje pouze na obsah relace, nikoli na cookie. Výchozí nastavení je 20 minut.
IOTimeout Maximální doba, po kterou je možné načíst relaci z úložiště nebo ji potvrdit zpět do úložiště. Toto nastavení se může vztahovat pouze na asynchronní operace. Tento časový limit lze zakázat pomocí InfiniteTimeSpan. Výchozí hodnota je 1 minuta.

Relace používá cookie ke sledování a identifikaci požadavků z jednoho prohlížeče. Ve výchozím nastavení se tento cookie název .AspNetCore.Sessionpoužívá a používá cestu /. cookie Vzhledem k tomu, že výchozí nastavení neurčuje doménu, není pro skript na straně klienta na stránce k dispozici (protože HttpOnly výchozí hodnota je true).

Chcete-li přepsat cookie výchozí hodnoty relace, použijte SessionOptions:

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

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

    services.AddControllersWithViews();
    services.AddRazorPages();
}

Aplikace pomocí IdleTimeout vlastnosti určuje, jak dlouho může být relace nečinná, než se její obsah v mezipaměti serveru opustí. Tato vlastnost je nezávislá na cookie vypršení platnosti. Každý požadavek, který prochází middlewarem relace, resetuje časový limit.

Stav relace není uzamčený. Pokud se dva požadavky současně pokusí upravit obsah relace, poslední požadavek přepíše první. Session je implementováno jako koherentní relace, což znamená, že veškerý obsah je uložen společně. Když se dva požadavky snaží upravit různé hodnoty relace, může poslední požadavek přepsat změny relace provedené prvním.

Nastavení a získání hodnot relace

Stav relace je přístupný z Razor třídy Pages PageModel nebo třídy MVC Controller s HttpContext.Session. Tato vlastnost je ISession implementace.

Implementace ISession poskytuje několik rozšiřujících metod pro nastavení a načtení celočíselné a řetězcové hodnoty. Metody rozšíření jsou v Microsoft.AspNetCore.Http oboru názvů.

ISession rozšiřující metody:

Následující příklad načte hodnotu relace pro IndexModel.SessionKeyName klíč (_Name v ukázkové aplikaci) na Razor stránce Pages:

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

...

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

Následující příklad ukazuje, jak nastavit a získat celé číslo a řetězec:

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

Všechna data relace musí být serializována, aby bylo možné povolit scénář distribuované mezipaměti, i když používáte mezipaměť v paměti. Řetězcové a celočíselné serializátory jsou poskytovány rozšiřujícími metodami ISession. Komplexní typy musí být serializovány uživatelem pomocí jiného mechanismu, například JSON.

K serializaciobjektůch

public static class SessionExtensions
{
    public static void Set<T>(this ISession session, string key, T value)
    {
        session.SetString(key, JsonSerializer.Serialize(value));
    }

    public static T Get<T>(this ISession session, string key)
    {
        var value = session.GetString(key);
        return value == null ? default : JsonSerializer.Deserialize<T>(value);
    }
}

Následující příklad ukazuje, jak nastavit a získat serializovatelný objekt s SessionExtensions třídou:

// Requires SessionExtensions from sample download.
if (HttpContext.Session.Get<DateTime>(SessionKeyTime) == default)
{
    HttpContext.Session.Set<DateTime>(SessionKeyTime, currentTime);
}

TempData

ASP.NET Core zpřístupňuje stránky tempdata nebo kontroleru TempData.Razor Tato vlastnost ukládá data, dokud se nepřečte v jiném požadavku. Metody Keep(String) a Peek(string) lze použít k prozkoumání dat bez odstranění na konci požadavku. Zachovejte značky všech položek ve slovníku pro uchovávání informací. TempData Je:

  • Užitečné pro přesměrování v případě, že se data vyžadují pro více než jeden požadavek.
  • Implementují TempData poskytovatelé pomocí stavu cookierelace nebo s.

Ukázky tempData

Představte si následující stránku, která vytvoří zákazníka:

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

Zobrazí se následující stránka TempData["Message"]:

@page
@model IndexModel

<h1>Peek Contacts</h1>

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

@*Content removed for brevity.*@

V předchozím kódu se na konci požadavku neodstraní, TempData["Message"]protože Peek se používá. Při aktualizaci stránky se zobrazí obsah souboru TempData["Message"].

Následující kód je podobný předchozímu kódu, ale používá Keep se k zachování dat na konci požadavku:

@page
@model IndexModel

<h1>Contacts Keep</h1>

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

@*Content removed for brevity.*@

Přechod mezi stránkami IndexPeek a IndexKeep se neodstraní TempData["Message"].

Následující kód se zobrazí TempData["Message"], ale na konci požadavku TempData["Message"] se odstraní:

@page
@model IndexModel

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

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

@*Content removed for brevity.*@

Zprostředkovatelé tempData

cookieZprostředkovatel TempData založený na databázi TempData se ve výchozím nastavení používá k ukládání tempData v scookie.

Data cookie se šifrují pomocí IDataProtectorzakódovaných Base64UrlTextEncoderdat a potom se zakódují. Maximální cookie velikost je menší než 4096 bajtů kvůli šifrování a bloků dat. Data cookie nejsou komprimovaná, protože komprese šifrovaných dat může vést k problémům se zabezpečením, jako jsou útoky CRIME a BREACH útoky. Další informace o poskytovateli tempdata založeném cookiena technologii TempData naleznete v tématu CookieTempDataProvider.

Volba zprostředkovatele TempData

Volba zprostředkovatele TempData zahrnuje několik aspektů, například:

  • Používá aplikace už stav relace? Pokud ano, použití poskytovatele TempData stavu relace nemá žádné další náklady na aplikaci nad rámec velikosti dat.
  • Používá aplikace tempData jen střídmě pro relativně malé objemy dat, až 500 bajtů? Pokud ano, cookie poskytovatel TempData přidá malé náklady na každý požadavek, který nese TempData. Pokud tomu tak není, může být poskytovatel tempData stavu relace výhodný, aby se zabránilo zaokrouhlení velkého množství dat v každém požadavku, dokud se tempData nespotřebuje.
  • Běží aplikace v serverové farmě na více serverech? Pokud ano, není nutná žádná další konfigurace pro použití cookie zprostředkovatele TempData mimo ochranu dat (viz ASP.NET Přehled základní ochrany dat a poskytovatelé úložiště klíčů).

Většina webových klientů, jako jsou webové prohlížeče, vynucuje omezení maximální velikosti každého cookie a celkového počtu cookies. Při použití cookie zprostředkovatele TempData ověřte, že aplikace tyto limity nepřekročí. Zvažte celkovou velikost dat. Účet se zvětší cookie kvůli šifrování a bloků dat.

Konfigurace zprostředkovatele TempData

Poskytovatel cookieTempData založený na technologii TempData je ve výchozím nastavení povolený.

Pokud chcete povolit zprostředkovatele TempData založeného na relaci, použijte metodu AddSessionStateTempDataProvider rozšíření. Vyžaduje se AddSessionStateTempDataProvider pouze jedno volání:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews()
        .AddSessionStateTempDataProvider();
    services.AddRazorPages()
        .AddSessionStateTempDataProvider();

    services.AddSession();
}

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

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseSession();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
        endpoints.MapRazorPages();
    });
}

Řetězce dotazů

Omezené množství dat je možné předat z jednoho požadavku do jiného přidáním do řetězce dotazu nového požadavku. To je užitečné pro trvalé zachycení stavu, které umožňuje sdílení propojení s vloženým stavem prostřednictvím e-mailu nebo sociálních sítí. Protože řetězce dotazu ADRESY URL jsou veřejné, nikdy nepoužívejte řetězce dotazů pro citlivá data.

Kromě nezamýšleného sdílení, včetně dat v řetězcích dotazů, může aplikace vystavit útokům CSRF (Cross-Site Request Forgery). Všechny zachované stavy relace musí chránit před útoky CSRF. Další informace najdete v tématu Prevence útoků založených na padělání žádosti posílané mezi weby (XSRF/CSRF) v ASP.NET Core.

Skrytá pole

Data lze uložit do skrytých polí formuláře a publikovat zpět na další požadavek. To je běžné ve vícestrákových formulářích. Vzhledem k tomu, že klient může potenciálně manipulovat s daty, musí aplikace vždy znovu obnovit data uložená ve skrytých polích.

HttpContext.Items

Kolekce HttpContext.Items se používá k ukládání dat při zpracování jednoho požadavku. Obsah kolekce se po zpracování požadavku zahodí. Kolekce Items se často používá k tomu, aby komponenty nebo middleware komunikovaly, když během požadavku pracují v různých bodech v čase a nemají přímý způsob předávání parametrů.

V následujícím příkladu middleware přidá isVerified do Items kolekce:

public void Configure(IApplicationBuilder app, ILogger<Startup> logger)
{
    app.UseRouting();

    app.Use(async (context, next) =>
    {
        logger.LogInformation($"Before setting: Verified: {context.Items["isVerified"]}");
        context.Items["isVerified"] = true;
        await next.Invoke();
    });

    app.Use(async (context, next) =>
    {
        logger.LogInformation($"Next: Verified: {context.Items["isVerified"]}");
        await next.Invoke();
    });

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGet("/", async context =>
        {
            await context.Response.WriteAsync($"Verified: {context.Items["isVerified"]}");
        });
    });
}

U middlewaru, který se používá jenom v jedné aplikaci, jsou pevné string klíče přijatelné. Middleware sdílený mezi aplikacemi by měl používat jedinečné klíče objektů, aby nedocházelo ke kolizím klíčů. Následující příklad ukazuje, jak použít jedinečný klíč objektu definovaný v middlewarové třídě:

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 app)
    {
        return app.UseMiddleware<HttpContextItemsMiddleware>();
    }
}

Jiný kód má přístup k hodnotě uložené v HttpContext.Items klíči vystavené middlewarovou třídou:

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

Tento přístup má také výhodu odstranění použití klíčových řetězců v kódu.

Cache

Ukládání do mezipaměti je efektivní způsob, jak ukládat a načítat data. Aplikace může řídit životnost položek uložených v mezipaměti. Další informace najdete v tématu Ukládání odpovědí do mezipaměti v ASP.NET Core.

Data uložená v mezipaměti nejsou přidružená ke konkrétnímu požadavku, uživateli nebo relaci. Neukádejte data specifická pro uživatele, která mohou být načtena jinými požadavky uživatelů.

Pokud chcete ukládat data do mezipaměti pro celou aplikaci, přečtěte si téma Mezipaměť v paměti v ASP.NET Core.

Běžné chyby

Pokud se middleware relace nepodaří zachovat relaci:

  • Middleware zaznamená výjimku a požadavek pokračuje normálně.
  • To vede k nepředvídatelným chováním.

Middleware relace nemůže zachovat relaci, pokud záložní úložiště není k dispozici. Uživatel například ukládá nákupní košík v relaci. Uživatel přidá položku do košíku, ale potvrzení se nezdaří. Aplikace o chybě neví, takže hlásí uživateli, že byla položka přidána do košíku, což není pravda.

Doporučeným přístupem ke kontrole chyb je volání await feature.Session.CommitAsync při zápisu aplikace do relace. CommitAsync vyvolá výjimku, pokud záložní úložiště není k dispozici. Pokud CommitAsync selže, aplikace může výjimku zpracovat. LoadAsync vyvolá za stejných podmínek, pokud úložiště dat není k dispozici.

Další materiály

Hostování ASP.NET Core ve webové farmě