Události
Mistrovství Světa v Power BI DataViz
14. 2. 16 - 31. 3. 16
Se 4 šance na vstup, můžete vyhrát konferenční balíček a udělat to na LIVE Grand Finale v Las Vegas
Další informaceTento prohlížeč se už nepodporuje.
Upgradujte na Microsoft Edge, abyste mohli využívat nejnovější funkce, aktualizace zabezpečení a technickou podporu.
Poznámka
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Upozornění
Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v zásadách podpory .NET a .NET Core. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Důležité
Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Autor: Rick Anderson a Steve Smith
Middleware je software sestavený do kanálu aplikace pro zpracování požadavků a odpovědí. Každá komponenta:
K sestavení kanálu požadavků se používají delegáti požadavků. Delegáti požadavků zpracovávají každý požadavek HTTP.
Delegáti požadavků se konfigurují pomocí rozšiřujících metod Run, Map a Use. Jednotlivý delegát požadavku může být zadán na řádku jako anonymní metoda (tzv. in-line middleware) nebo může být definován v opakovaně použitelné třídě. Tyto opakovaně použitelné třídy a vložené anonymní metody jsou middleware, označované také jako komponenty middlewaru. Každá komponenta middlewaru v kanálu požadavků zodpovídá za vyvolání další komponenty v kanálu nebo zkratování kanálu. Když middleware zkratuje, označuje se jako terminální middleware, protože brání dalšímu middlewaru ve zpracování požadavku.
Téma věnované migraci obslužných rutin HTTP a modulů do middlewaru ASP.NET Core vysvětluje rozdíl mezi kanály požadavků v prostředích ASP.NET Core a ASP.NET 4.x a poskytuje další ukázky middlewaru.
Blazor Web Apps, Razor Pages a MVC zpracovávají požadavky prohlížeče na serveru pomocí middlewaru. Pokyny v tomto článku platí pro tyto typy aplikací.
Samostatné Blazor WebAssembly aplikace běží zcela na klientovi a nezpracují požadavky pomocí kanálu middlewaru. Pokyny v tomto článku se nevztahují na samostatné Blazor WebAssembly aplikace.
ASP.NET Core obsahuje celou řadu analyzátorů Compile Platform, které kontrolují kód aplikace z hlediska kvality. Další informace najdete v tématu Analýza kódu v aplikacích ASP.NET Core.
Kanál požadavků ASP.NET Core se skládá z posloupnosti delegátů požadavků, kteří se volají jeden po druhém. Tento koncept demonstruje následující schéma. Vlákno spouštění postupuje podle černých šipek.
Každý delegát může provádět operace před a za dalším delegátem. Delegáti zpracování výjimek by se měli volat v rané fázi zpracování kanálu, aby mohli zachytit výjimky, ke kterým dochází v pozdějších fázích zpracování kanálu.
Nejjednodušší možná aplikace ASP.NET Core nastavuje jednoho delegáta požadavků, který zpracovává všechny požadavky. Tento případ nezahrnuje vlastní kanál požadavků. Místo toho se jako reakce na každý požadavek HTTP volá jedna anonymní funkce.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Run(async context =>
{
await context.Response.WriteAsync("Hello world!");
});
app.Run();
Zřetězte několik delegátů požadavků společně s Use. Parametr next
představuje dalšího delegáta v kanálu. Kanál můžete zkratovat tak, že parametr next
. Obvykle můžete provádět akce před delegátem next
i po něm, jak ukazuje následující příklad:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Use(async (context, next) =>
{
// Do work that can write to the Response.
await next.Invoke();
// Do logging or other work that doesn't write to the Response.
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from 2nd delegate.");
});
app.Run();
Pokud delegát nepředá požadavek dalšímu delegátovi, označuje se to jako zkratování kanálu požadavků. Zkratování je často žádoucí, protože zabraňuje zbytečné práci. Například middleware statického souboru může fungovat jako terminálový middleware zpracováním požadavku na statický soubor a přeskočením zbytku zpracování. Middleware přidaný do kanálu před middleware, který ukončí další zpracování, stále zpracovává kód po příslušných příkazech next.Invoke
. Ohledně pokusu o zápis do již odeslané odpovědi si však projděte následující upozornění.
Upozornění
Nevolejte next.Invoke
během odpovědi nebo po odeslání odpovědi klientovi.
HttpResponse Po spuštění změny způsobí výjimku. Například nastavení hlaviček a stavového kódu vyvolá výjimku po spuštění odpovědi. Zápis do textu odpovědi po volání next
:
Content-Length
.HasStarted je užitečná nápověda indikující, jestli byly odeslány hlavičky nebo zapisováno do textu.
Další informace najdete v tématu Middleware s krátkým okruhem po směrování.
Delegáti Run neobdrží parametr next
. První delegát Run
je vždy terminální a ukončí kanál. Použití Run
je obvyklá konvence. Některé komponenty middlewaru můžou zpřístupnit metody Run[Middleware]
, které běží na konci kanálu:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Use(async (context, next) =>
{
// Do work that can write to the Response.
await next.Invoke();
// Do logging or other work that doesn't write to the Response.
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from 2nd delegate.");
});
app.Run();
Pokud chcete zobrazit komentáře ke kódu přeložené do jiných jazyků, než je angličtina, dejte nám vědět v této diskuzi na GitHubu.
V předchozím příkladu delegát Run
zapíše "Hello from 2nd delegate."
do odpovědi a pak ukončí kanál. Pokud je za delegáta Use
přidán jiný delegát Run
nebo Run
, nevolá se.
Rozšiřující metoda app.Use bez přidělování:
next
.Další informace najdete u tohoto problému na GitHubu.
Následující diagram znázorňuje kompletní kanál zpracování požadavků pro aplikace ASP.NET Core MVC a Razor Pages. Můžete si prohlédnout, jak je v typické aplikaci uspořádané stávající middlewary seřazené a kde se přidávají vlastní middlewary. Máte plnou kontrolu nad tím, jak změnit pořadí stávajících middlewarů nebo vložit nové vlastní middlewary podle potřeby vašich scénářů.
Middleware Endpoint v předchozím diagramu spustí kanál filtru pro odpovídající typ aplikace – MVC nebo Razor Pages.
Middleware Routing v předchozím diagramu je zobrazený za Static Files. Toto je pořadí, které šablony projektů implementují explicitním voláním app.UseRouting. Pokud nezavoláte app.UseRouting
, ve výchozím nastavení se middleware Routing spustí na začátku kanálu. Další informace najdete v tématu Směrování.
Pořadí, ve kterém jsou komponenty middlewaru přidány do souboru Program.cs
, definuje pořadí, ve kterém se komponenty middlewaru vyvolávají pro požadavky, a obrácené pořadí pro odpovědi. Toto pořadí má zásadní důležitost pro zabezpečení, výkon a funkce.
Následující zvýrazněný kód v Program.cs
přidává komponenty middlewaru související se zabezpečením v typickém doporučeném pořadí:
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebMiddleware.Data;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
// app.UseCookiePolicy();
app.UseRouting();
// app.UseRateLimiter();
// app.UseRequestLocalization();
// app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
// app.UseSession();
// app.UseResponseCompression();
// app.UseResponseCaching();
app.MapRazorPages();
app.MapDefaultControllerRoute();
app.Run();
V předchozím kódu:
UseCors
, UseAuthentication
a UseAuthorization
musí být v uvedeném pořadí.UseCors
musí aktuálně být před UseResponseCaching
. Tento požadavek je vysvětlený v problému s dotnet/aspnetcore #23218 na GitHubu.UseRequestLocalization
musí se zobrazit před jakýmkoli middlewarem, který může zkontrolovat jazykovou verzi požadavku, app.UseStaticFiles()
například .UseRouting
použití rozhraní API pro omezení rychlosti pro konkrétní koncové body. Pokud je například [EnableRateLimiting]
použit atribut, UseRateLimiter
musí být volána za UseRouting
. Při volání pouze globálních limiterů UseRateLimiter
lze volat před UseRouting
.V některých scénářích má middleware jiné řazení. Například pořadí ukládání do mezipaměti a komprese je specifické pro daný scénář a existuje několik platných pořadí. Příklad:
app.UseResponseCaching();
app.UseResponseCompression();
V předchozím kódu by bylo možné snížit využití procesoru uložením komprimované odpovědi do mezipaměti, ale mohlo by se stát, že budete ukládat do mezipaměti více reprezentací prostředku pomocí různých kompresních algoritmů, jako jsou například Gzip nebo Brotli.
Následující pořadí kombinuje statické soubory, aby se umožnilo ukládání komprimovaných statických souborů do mezipaměti:
app.UseResponseCaching();
app.UseResponseCompression();
app.UseStaticFiles();
Následující kód Program.cs
přidá komponenty middlewaru pro běžné scénáře aplikací:
Strict-Transport-Security
.if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.MapRazorPages();
V předchozím ukázkovém kódu je každá rozšiřující metoda middlewaru zpřístupněná v WebApplicationBuilder prostřednictvím oboru názvů Microsoft.AspNetCore.Builder.
UseExceptionHandler je první komponenta middlewaru přidaná do kanálu. Proto middleware Exception Handler zachycuje všechny výjimky, ke kterým dochází v pozdějších voláních.
Middleware Static File se volá v rané fázi zpracování kanálu, aby mohl zpracovávat požadavky a provést zkratování, aniž by se musely projít zbývající komponenty. Middleware Static File neposkytuje žádné kontroly autorizace. Všechny soubory obsluhované middlewarem Static File, včetně souborů pod wwwroot, jsou veřejně dostupné. Informace o přístupu k zabezpečení statických souborů najdete v tématu Statické soubory v ASP.NET Core.
Pokud požadavek nezpracuje middleware Static File, předá se do middlewaru Authentication (UseAuthentication), který provádí ověřování. Ověřování nezpůsobí zkratování neověřených požadavků. I když middleware Authentication ověřuje požadavky, autorizace (a zamítnutí) nastane až poté, co MVC vybere konkrétní kontroler MVC nebo Razor Pages a akci.
Následující příklad ukazuje pořadí middlewaru, ve kterém požadavky pro statické soubory zpracovává middleware Static File před middlewarem Response Compression. Statické soubory nejsou při tomto uspořádání middlewaru komprimovány. Odpovědi Razor Pages je možné komprimovat.
// Static files aren't compressed by Static File Middleware.
app.UseStaticFiles();
app.UseRouting();
app.UseResponseCompression();
app.MapRazorPages();
Informace o jednostrákových aplikacích najdete v tématu Přehled jednostrákových aplikací (SPA) v ASP.NET Core.
Pořadí volání UseCors
a UseStaticFiles
závisí na aplikaci. Další informace najdete v tématu Pořadí UseCors a UseStaticFiles
Middleware Forwarded Headers by měl běžet před ostatním middlewarem. Toto řazení zajišťuje, že middleware, který spoléhá na informace předávaných hlaviček, může využívat hodnoty hlaviček ke zpracování. Pokud chcete middleware Forwarded Headers spustit po diagnostice a middlewaru pro zpracování chyb, přečtěte si téma Middleware Ordered Headers.
Rozšíření Map se používají jako konvence pro větvení kanálu.
Map
rozvětví kanál požadavku na základě shod dané cesty k požadavku. Pokud cesta k požadavku začíná danou cestou, větev se spustí.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Map("/map1", HandleMapTest1);
app.Map("/map2", HandleMapTest2);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
app.Run();
static void HandleMapTest1(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 1");
});
}
static void HandleMapTest2(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 2");
});
}
Následující tabulka ukazuje požadavky a odpovědi z http://localhost:1234
s využitím předchozího kódu.
Požádat | Response |
---|---|
localhost:1234 | Hello from non-Map delegate. |
localhost:1234/map1 | Map Test 1 |
localhost:1234/map2 | Map Test 2 |
localhost:1234/map3 | Hello from non-Map delegate. |
Při použití Map
se odpovídající segmenty cest odeberou z HttpRequest.Path
a připojí ke HttpRequest.PathBase
pro každý požadavek.
Map
podporuje vnoření, například:
app.Map("/level1", level1App => {
level1App.Map("/level2a", level2AApp => {
// "/level1/level2a" processing
});
level1App.Map("/level2b", level2BApp => {
// "/level1/level2b" processing
});
});
Map
také může odpovídat více segmentům najednou:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Map("/map1/seg1", HandleMultiSeg);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
app.Run();
static void HandleMultiSeg(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 1");
});
}
MapWhen rozvětví kanál požadavku na základě výsledku daného predikátu. K mapování požadavků na novou větev kanálu je možné použít jakýkoli predikát typu Func<HttpContext, bool>
. V následujícím příkladu se predikát používá ke zjištění přítomnosti proměnné řetězce dotazu branch
:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapWhen(context => context.Request.Query.ContainsKey("branch"), HandleBranch);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
app.Run();
static void HandleBranch(IApplicationBuilder app)
{
app.Run(async context =>
{
var branchVer = context.Request.Query["branch"];
await context.Response.WriteAsync($"Branch used = {branchVer}");
});
}
Následující tabulka ukazuje požadavky a odpovědi z http://localhost:1234
s využitím předchozího kódu:
Požádat | Response |
---|---|
localhost:1234 |
Hello from non-Map delegate. |
localhost:1234/?branch=main |
Branch used = main |
UseWhen také rozvětví kanál požadavku na základě výsledku daného predikátu. Na rozdíl od MapWhen
se tato větev znovu připojí k hlavnímu potrubí, pokud neobsahuje terminální middleware.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseWhen(context => context.Request.Query.ContainsKey("branch"),
appBuilder => HandleBranchAndRejoin(appBuilder));
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
app.Run();
void HandleBranchAndRejoin(IApplicationBuilder app)
{
var logger = app.ApplicationServices.GetRequiredService<ILogger<Program>>();
app.Use(async (context, next) =>
{
var branchVer = context.Request.Query["branch"];
logger.LogInformation("Branch used = {branchVer}", branchVer);
// Do work that doesn't write to the Response.
await next();
// Do other work that doesn't write to the Response.
});
}
V předchozím příkladu se pro všechny požadavky zapíše odpověď Hello from non-Map delegate.
. Pokud požadavek obsahuje proměnnou řetězce dotazu branch
, před opětovným připojením k hlavnímu kanálu se zaprotokoluje její hodnota.
ASP.NET Core se dodává s následujícími komponentami middlewaru. Sloupec Pořadí obsahuje poznámky k umístění middlewaru v kanálu zpracování požadavků a to, za jakých podmínek může middleware ukončit zpracování požadavků. Když middleware zkratuje kanál zpracování požadavků a zabrání dalšímu navazujícímu middlewaru zpracovat požadavek, označuje se jako terminální middleware. Další informace o zkratování najdete v části Vytvoření middlewarového kanálu s webapplication .
Middleware | Popis | Objednávka |
---|---|---|
Authentication | Poskytuje podporu ověřování. | Než je potřeba HttpContext.User . Terminál pro zpětné volání OAuth. |
Autorizace | Poskytuje podporu autorizace. | Okamžitě po middlewaru Authentication. |
Cookie Policy | Sleduje souhlas uživatelů s ukládáním osobních údajů a vynucuje minimální standardy pro pole cookie, například secure a SameSite . |
Než middleware vydá soubory cookie. Příklady: Authentication, Session, MVC (TempData). |
CORS | Konfiguruje sdílení prostředků mezi zdroji (CORS). | Před komponentami, které používají CORS.
UseCors v současné době musí předcházet před UseResponseCaching , a to kvůli této chybě. |
DeveloperExceptionPage | Vygeneruje stránku s informacemi o chybách, které jsou určené jenom pro použití ve vývojovém prostředí. | Před komponentami, které generují chyby. V případě vývojového prostředí šablony projektů automaticky zaregistrují tento middleware jako první middleware v kanálu. |
Diagnostika | Několik samostatných middlewarů, které poskytují stránku výjimek pro vývojáře, zpracování výjimek, stránky stavových kódů a výchozí webovou stránku pro nové aplikace. | Před komponentami, které generují chyby. Terminál pro výjimky nebo obsluhu výchozí webové stránky pro nové aplikace. |
Forwarded Headers | Předá přeposílané hlavičky do aktuálního požadavku. | Před komponentami, které využívají aktualizovaná pole. Příklady: Schéma, hostitel, IP adresa klienta, metoda. |
Health Check | Kontroluje stav aplikace ASP.NET Core a jejích závislostí, jako je kontrola dostupnosti databáze. | Terminál, pokud požadavek odpovídá koncovému bodu kontroly stavu. |
Header Propagation | Šíří hlavičky HTTP z příchozího požadavku do odchozích požadavků klienta HTTP. | |
Protokolování HTTP | Protokoluje požadavky HTTP a odpovědi. | Na začátku kanálu middlewaru. |
HTTP Method Override | Umožňuje, aby příchozí požadavek POST přepsal metodu. | Před komponentami, které využívají aktualizovanou metodu. |
HTTPS Redirection | Přesměruje všechny požadavky HTTP na HTTPS. | Před komponentami, které využívají danou adresu URL. |
HTTP Strict Transport Security (HSTS) | Middleware pro vylepšení zabezpečení, který přidává speciální hlavičku odpovědi. | Před odesláním odpovědí a po komponentách, které upravují požadavky. Příklady: Přeposílané hlavičky, přepsání adresy URL. |
MVC | Zpracovává požadavky s využitím MVC / Razor Pages. | Terminál, pokud požadavek odpovídá trase. |
OWIN | Spolupracuje s aplikacemi, servery a middlewarem založenými na OWIN. | Terminál, pokud middleware OWIN plně zpracuje daný požadavek. |
Ukládání výstupu do mezipaměti | Poskytuje podporu pro ukládání odpovědí do mezipaměti na základě konfigurace. | Před komponentami, které vyžadují ukládání do mezipaměti. Je potřeba použít UseRouting před UseOutputCaching . Je potřeba použít UseCORS před UseOutputCaching . |
Ukládání odpovědí do mezipaměti | Poskytuje podporu pro ukládání odpovědí do mezipaměti. To vyžaduje, aby klientská účast fungovala. K úplnému řízení serveru použijte ukládání výstupu do mezipaměti. | Před komponentami, které vyžadují ukládání do mezipaměti. Je potřeba použít UseCORS před UseResponseCaching . Aplikace uživatelského rozhraní, jako Razor jsou stránky, obvykle nejsou užitečné, protože prohlížeče obvykle nastavují hlavičky požadavků, které brání ukládání do mezipaměti.
Ukládání výstupu do mezipaměti přináší výhody aplikací uživatelského rozhraní. |
Request Decompression | Poskytuje podporu pro dekompresi požadavků. | Před komponentami, které čtou text požadavku. |
Response Compression | Poskytuje podporu pro kompresi odpovědí. | Před komponentami, které vyžadují kompresi. |
Request Localization | Poskytuje podporu lokalizace. | Před komponentami citlivými na lokalizaci. Při použití RouteDataRequestCultureProvider musí následovat po middlewaru Routing. |
Časové limity požadavků | Poskytuje podporu pro konfiguraci časových limitů požadavků, globálního a koncového bodu. |
UseRequestTimeouts musí přijít po UseExceptionHandler , UseDeveloperExceptionPage a UseRouting . |
Endpoint Routing | Definuje a omezuje trasy požadavků. | Terminál pro vyhovující trasy. |
SPA | Zpracovává všechny požadavky od tohoto bodu v řetězci middlewaru vrácením výchozí stránky pro jednostránkovou aplikaci (SPA). | U konce řetězce, aby měl přednost ostatní middleware pro obsluhu statických souborů, akcí MVC atd. |
Relace | Poskytuje podporu pro správu uživatelských relací. | Před komponentami, které vyžadují middleware Session. |
Static Files | Poskytuje podporu pro obsluhu statických souborů a procházení adresářů. | Terminál, pokud požadavek odpovídá souboru. |
Přepsání adresy URL | Poskytuje podporu pro přepis adres URL a přesměrování požadavků. | Před komponentami, které využívají danou adresu URL. |
W3CLogging | Generuje protokoly přístupu k serveru v rozšířeném formátu souborů protokolu W3C. | Na začátku kanálu middlewaru. |
Webové sokety | Povoluje protokol WebSocket. | Před komponentami, které jsou potřeba k přijetí požadavků WebSocket. |
Autor: Rick Anderson a Steve Smith
Middleware je software sestavený do kanálu aplikace pro zpracování požadavků a odpovědí. Každá komponenta:
K sestavení kanálu požadavků se používají delegáti požadavků. Delegáti požadavků zpracovávají každý požadavek HTTP.
Delegáti požadavků se konfigurují pomocí rozšiřujících metod Run, Map a Use. Jednotlivý delegát požadavku může být zadán na řádku jako anonymní metoda (tzv. in-line middleware) nebo může být definován v opakovaně použitelné třídě. Tyto opakovaně použitelné třídy a vložené anonymní metody jsou middleware, označované také jako komponenty middlewaru. Každá komponenta middlewaru v kanálu požadavků zodpovídá za vyvolání další komponenty v kanálu nebo zkratování kanálu. Když middleware zkratuje, označuje se jako terminální middleware, protože brání dalšímu middlewaru ve zpracování požadavku.
Téma věnované migraci obslužných rutin HTTP a modulů do middlewaru ASP.NET Core vysvětluje rozdíl mezi kanály požadavků v prostředích ASP.NET Core a ASP.NET 4.x a poskytuje další ukázky middlewaru.
Razor Pages, MVC, Blazor Servera hostovaný projekt na straně serveru řešení Blazor WebAssembly, které zpracovává požadavky prohlížeče na serveru s middlewarem. Pokyny v tomto článku platí pro tyto typy aplikací.
Samostatné Blazor WebAssembly aplikace běží zcela na klientovi a nezpracují požadavky pomocí kanálu middlewaru. Pokyny v tomto článku se nevztahují na samostatné Blazor WebAssembly aplikace.
ASP.NET Core obsahuje celou řadu analyzátorů Compile Platform, které kontrolují kód aplikace z hlediska kvality. Další informace najdete v tématu Analýza kódu v aplikacích ASP.NET Core.
Kanál požadavků ASP.NET Core se skládá z posloupnosti delegátů požadavků, kteří se volají jeden po druhém. Tento koncept demonstruje následující schéma. Vlákno spouštění postupuje podle černých šipek.
Každý delegát může provádět operace před a za dalším delegátem. Delegáti zpracování výjimek by se měli volat v rané fázi zpracování kanálu, aby mohli zachytit výjimky, ke kterým dochází v pozdějších fázích zpracování kanálu.
Nejjednodušší možná aplikace ASP.NET Core nastavuje jednoho delegáta požadavků, který zpracovává všechny požadavky. Tento případ nezahrnuje vlastní kanál požadavků. Místo toho se jako reakce na každý požadavek HTTP volá jedna anonymní funkce.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Run(async context =>
{
await context.Response.WriteAsync("Hello world!");
});
app.Run();
Zřetězte několik delegátů požadavků společně s Use. Parametr next
představuje dalšího delegáta v kanálu. Kanál můžete zkratovat tak, že parametr next
. Obvykle můžete provádět akce před delegátem next
i po něm, jak ukazuje následující příklad:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Use(async (context, next) =>
{
// Do work that can write to the Response.
await next.Invoke();
// Do logging or other work that doesn't write to the Response.
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from 2nd delegate.");
});
app.Run();
Pokud delegát nepředá požadavek dalšímu delegátovi, označuje se to jako zkratování kanálu požadavků. Zkratování je často žádoucí, protože zabraňuje zbytečné práci. Například Middleware statického souboru může fungovat jako terminálový middleware zpracováním požadavku na statický soubor a přerušením zbytku řetězce. Middleware přidaný do kanálu před middleware, který ukončí další zpracování, stále zpracovává kód po příslušných příkazech next.Invoke
. Ohledně pokusu o zápis do již odeslané odpovědi si však projděte následující upozornění.
Upozornění
Po odeslání odpovědi klientovi nevolejte next.Invoke
. Změny v HttpResponse po spuštění odpovědi vyvolají výjimku. Například nastavení hlaviček a stavového kódu vyvolá výjimku. Zápis do textu odpovědi po volání next
:
Content-Length
.HasStarted je užitečná nápověda indikující, jestli byly odeslány hlavičky nebo zapisováno do textu.
Delegáti Run neobdrží parametr next
. První delegát Run
je vždy terminální a ukončí kanál. Použití Run
je obvyklá konvence. Některé komponenty middlewaru můžou zpřístupnit metody Run[Middleware]
, které běží na konci kanálu:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Use(async (context, next) =>
{
// Do work that can write to the Response.
await next.Invoke();
// Do logging or other work that doesn't write to the Response.
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from 2nd delegate.");
});
app.Run();
Pokud chcete zobrazit komentáře ke kódu přeložené do jiných jazyků, než je angličtina, dejte nám vědět v této diskuzi na GitHubu.
V předchozím příkladu delegát Run
zapíše "Hello from 2nd delegate."
do odpovědi a pak ukončí kanál. Pokud je za delegáta Use
přidán jiný delegát Run
nebo Run
, nevolá se.
Rozšiřující metoda app.Use bez přidělování:
next
.Další informace najdete u tohoto problému na GitHubu.
Následující diagram znázorňuje kompletní kanál zpracování požadavků pro aplikace ASP.NET Core MVC a Razor Pages. Můžete si prohlédnout, jak je v typické aplikaci uspořádané stávající middlewary seřazené a kde se přidávají vlastní middlewary. Máte plnou kontrolu nad tím, jak změnit pořadí stávajících middlewarů nebo vložit nové vlastní middlewary podle potřeby vašich scénářů.
Middleware Endpoint v předchozím diagramu spustí kanál filtru pro odpovídající typ aplikace – MVC nebo Razor Pages.
Middleware Routing v předchozím diagramu je zobrazený za Static Files. Toto je pořadí, které šablony projektů implementují explicitním voláním app.UseRouting. Pokud nezavoláte app.UseRouting
, ve výchozím nastavení se middleware Routing spustí na začátku kanálu. Další informace najdete v tématu Směrování.
Pořadí, ve kterém jsou komponenty middlewaru přidány do souboru Program.cs
, definuje pořadí, ve kterém se komponenty middlewaru vyvolávají pro požadavky, a obrácené pořadí pro odpovědi. Toto pořadí má zásadní důležitost pro zabezpečení, výkon a funkce.
Následující zvýrazněný kód v Program.cs
přidává komponenty middlewaru související se zabezpečením v typickém doporučeném pořadí:
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebMiddleware.Data;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
// app.UseCookiePolicy();
app.UseRouting();
// app.UseRateLimiter();
// app.UseRequestLocalization();
// app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
// app.UseSession();
// app.UseResponseCompression();
// app.UseResponseCaching();
app.MapRazorPages();
app.MapDefaultControllerRoute();
app.Run();
V předchozím kódu:
UseCors
, UseAuthentication
a UseAuthorization
musí být v uvedeném pořadí.UseCors
musí aktuálně být před UseResponseCaching
. Tento požadavek je vysvětlený v problému s dotnet/aspnetcore #23218 na GitHubu.UseRequestLocalization
musí se zobrazit před jakýmkoli middlewarem, který může zkontrolovat jazykovou verzi požadavku, app.UseStaticFiles()
například .UseRouting
použití rozhraní API pro omezení rychlosti pro konkrétní koncové body. Pokud je například [EnableRateLimiting]
použit atribut, UseRateLimiter
musí být volána za UseRouting
. Při volání pouze globálních limiterů UseRateLimiter
lze volat před UseRouting
.V některých scénářích má middleware jiné řazení. Například pořadí ukládání do mezipaměti a komprese je specifické pro daný scénář a existuje několik platných pořadí. Příklad:
app.UseResponseCaching();
app.UseResponseCompression();
V předchozím kódu by bylo možné snížit využití procesoru uložením komprimované odpovědi do mezipaměti, ale mohlo by se stát, že budete ukládat do mezipaměti více reprezentací prostředku pomocí různých kompresních algoritmů, jako jsou například Gzip nebo Brotli.
Následující pořadí kombinuje statické soubory, aby se umožnilo ukládání komprimovaných statických souborů do mezipaměti:
app.UseResponseCaching();
app.UseResponseCompression();
app.UseStaticFiles();
Následující kód Program.cs
přidá komponenty middlewaru pro běžné scénáře aplikací:
Strict-Transport-Security
.if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.MapRazorPages();
V předchozím ukázkovém kódu je každá rozšiřující metoda middlewaru zpřístupněná v WebApplicationBuilder prostřednictvím oboru názvů Microsoft.AspNetCore.Builder.
UseExceptionHandler je první komponenta middlewaru přidaná do kanálu. Proto middleware Exception Handler zachycuje všechny výjimky, ke kterým dochází v pozdějších voláních.
Middleware Static File se volá v rané fázi zpracování kanálu, aby mohl zpracovávat požadavky a provést zkratování, aniž by se musely projít zbývající komponenty. Middleware Static File neposkytuje žádné kontroly autorizace. Všechny soubory obsluhované middlewarem Static File, včetně souborů pod wwwroot, jsou veřejně dostupné. Informace o přístupu k zabezpečení statických souborů najdete v tématu Statické soubory v ASP.NET Core.
Pokud požadavek nezpracuje middleware Static File, předá se do middlewaru Authentication (UseAuthentication), který provádí ověřování. Ověřování nezpůsobí zkratování neověřených požadavků. I když middleware Authentication ověřuje požadavky, autorizace (a zamítnutí) nastane až poté, co MVC vybere konkrétní kontroler MVC nebo Razor Pages a akci.
Následující příklad ukazuje pořadí middlewaru, ve kterém požadavky pro statické soubory zpracovává middleware Static File před middlewarem Response Compression. Statické soubory nejsou při tomto uspořádání middlewaru komprimovány. Odpovědi Razor Pages je možné komprimovat.
// Static files aren't compressed by Static File Middleware.
app.UseStaticFiles();
app.UseRouting();
app.UseResponseCompression();
app.MapRazorPages();
Informace o jednostránkových aplikacích najdete v průvodcích pro šablony projektů React a Angular.
Pořadí volání UseCors
a UseStaticFiles
závisí na aplikaci. Další informace najdete v tématu Pořadí UseCors a UseStaticFiles
Middleware Forwarded Headers by měl běžet před ostatním middlewarem. Toto řazení zajišťuje, že middleware, který spoléhá na informace předávaných hlaviček, může využívat hodnoty hlaviček ke zpracování. Pokud chcete middleware Forwarded Headers spustit po diagnostice a middlewaru pro zpracování chyb, přečtěte si téma Middleware Ordered Headers.
Rozšíření Map se používají jako konvence pro větvení kanálu.
Map
rozvětví kanál požadavku na základě shod dané cesty k požadavku. Pokud cesta k požadavku začíná danou cestou, větev se spustí.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Map("/map1", HandleMapTest1);
app.Map("/map2", HandleMapTest2);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
app.Run();
static void HandleMapTest1(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 1");
});
}
static void HandleMapTest2(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 2");
});
}
Následující tabulka ukazuje požadavky a odpovědi z http://localhost:1234
s využitím předchozího kódu.
Požádat | Response |
---|---|
localhost:1234 | Hello from non-Map delegate. |
localhost:1234/map1 | Map Test 1 |
localhost:1234/map2 | Map Test 2 |
localhost:1234/map3 | Hello from non-Map delegate. |
Při použití Map
se odpovídající segmenty cest odeberou z HttpRequest.Path
a připojí ke HttpRequest.PathBase
pro každý požadavek.
Map
podporuje vnoření, například:
app.Map("/level1", level1App => {
level1App.Map("/level2a", level2AApp => {
// "/level1/level2a" processing
});
level1App.Map("/level2b", level2BApp => {
// "/level1/level2b" processing
});
});
Map
také může odpovídat více segmentům najednou:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Map("/map1/seg1", HandleMultiSeg);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
app.Run();
static void HandleMultiSeg(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 1");
});
}
MapWhen rozvětví kanál požadavku na základě výsledku daného predikátu. K mapování požadavků na novou větev kanálu je možné použít jakýkoli predikát typu Func<HttpContext, bool>
. V následujícím příkladu se predikát používá ke zjištění přítomnosti proměnné řetězce dotazu branch
:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapWhen(context => context.Request.Query.ContainsKey("branch"), HandleBranch);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
app.Run();
static void HandleBranch(IApplicationBuilder app)
{
app.Run(async context =>
{
var branchVer = context.Request.Query["branch"];
await context.Response.WriteAsync($"Branch used = {branchVer}");
});
}
Následující tabulka ukazuje požadavky a odpovědi z http://localhost:1234
s využitím předchozího kódu:
Požádat | Response |
---|---|
localhost:1234 |
Hello from non-Map delegate. |
localhost:1234/?branch=main |
Branch used = main |
UseWhen také rozvětví kanál požadavku na základě výsledku daného predikátu. Na rozdíl od MapWhen
se tato větev znovu připojí k hlavnímu kanálu, pokud nezpůsobí zkratování nebo neobsahuje terminální middleware:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseWhen(context => context.Request.Query.ContainsKey("branch"),
appBuilder => HandleBranchAndRejoin(appBuilder));
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
app.Run();
void HandleBranchAndRejoin(IApplicationBuilder app)
{
var logger = app.ApplicationServices.GetRequiredService<ILogger<Program>>();
app.Use(async (context, next) =>
{
var branchVer = context.Request.Query["branch"];
logger.LogInformation("Branch used = {branchVer}", branchVer);
// Do work that doesn't write to the Response.
await next();
// Do other work that doesn't write to the Response.
});
}
V předchozím příkladu se pro všechny požadavky zapíše odpověď Hello from non-Map delegate.
. Pokud požadavek obsahuje proměnnou řetězce dotazu branch
, před opětovným připojením k hlavnímu kanálu se zaprotokoluje její hodnota.
ASP.NET Core se dodává s následujícími komponentami middlewaru. Sloupec Pořadí obsahuje poznámky k umístění middlewaru v kanálu zpracování požadavků a to, za jakých podmínek může middleware ukončit zpracování požadavků. Když middleware zkratuje kanál zpracování požadavků a zabrání dalšímu navazujícímu middlewaru zpracovat požadavek, označuje se jako terminální middleware. Další informace o zkratování najdete v části Vytvoření middlewarového kanálu s webapplication .
Middleware | Popis | Objednávka |
---|---|---|
Authentication | Poskytuje podporu ověřování. | Než je potřeba HttpContext.User . Terminál pro zpětné volání OAuth. |
Autorizace | Poskytuje podporu autorizace. | Okamžitě po middlewaru Authentication. |
Cookie Policy | Sleduje souhlas uživatelů s ukládáním osobních údajů a vynucuje minimální standardy pro pole cookie, například secure a SameSite . |
Než middleware vydá soubory cookie. Příklady: Authentication, Session, MVC (TempData). |
CORS | Konfiguruje sdílení prostředků mezi zdroji (CORS). | Před komponentami, které používají CORS.
UseCors v současné době musí předcházet před UseResponseCaching , a to kvůli této chybě. |
DeveloperExceptionPage | Vygeneruje stránku s informacemi o chybách, které jsou určené jenom pro použití ve vývojovém prostředí. | Před komponentami, které generují chyby. V případě vývojového prostředí šablony projektů automaticky zaregistrují tento middleware jako první middleware v kanálu. |
Diagnostika | Několik samostatných middlewarů, které poskytují stránku výjimek pro vývojáře, zpracování výjimek, stránky stavových kódů a výchozí webovou stránku pro nové aplikace. | Před komponentami, které generují chyby. Terminál pro výjimky nebo obsluhu výchozí webové stránky pro nové aplikace. |
Forwarded Headers | Předá přeposílané hlavičky do aktuálního požadavku. | Před komponentami, které využívají aktualizovaná pole. Příklady: Schéma, hostitel, IP adresa klienta, metoda. |
Health Check | Kontroluje stav aplikace ASP.NET Core a jejích závislostí, jako je kontrola dostupnosti databáze. | Terminál, pokud požadavek odpovídá koncovému bodu kontroly stavu. |
Header Propagation | Šíří hlavičky HTTP z příchozího požadavku do odchozích požadavků klienta HTTP. | |
Protokolování HTTP | Protokoluje požadavky HTTP a odpovědi. | Na začátku kanálu middlewaru. |
HTTP Method Override | Umožňuje, aby příchozí požadavek POST přepsal metodu. | Před komponentami, které využívají aktualizovanou metodu. |
HTTPS Redirection | Přesměruje všechny požadavky HTTP na HTTPS. | Před komponentami, které využívají danou adresu URL. |
HTTP Strict Transport Security (HSTS) | Middleware pro vylepšení zabezpečení, který přidává speciální hlavičku odpovědi. | Před odesláním odpovědí a po komponentách, které upravují požadavky. Příklady: Přeposílané hlavičky, přepsání adresy URL. |
MVC | Zpracovává požadavky s využitím MVC / Razor Pages. | Terminál, pokud požadavek odpovídá trase. |
OWIN | Spolupracuje s aplikacemi, servery a middlewarem založenými na OWIN. | Terminál, pokud middleware OWIN plně zpracuje daný požadavek. |
Ukládání výstupu do mezipaměti | Poskytuje podporu pro ukládání odpovědí do mezipaměti na základě konfigurace. | Před komponentami, které vyžadují ukládání do mezipaměti. Je potřeba použít UseRouting před UseOutputCaching . Je potřeba použít UseCORS před UseOutputCaching . |
Ukládání odpovědí do mezipaměti | Poskytuje podporu pro ukládání odpovědí do mezipaměti. To vyžaduje, aby klientská účast fungovala. K úplnému řízení serveru použijte ukládání výstupu do mezipaměti. | Před komponentami, které vyžadují ukládání do mezipaměti. Je potřeba použít UseCORS před UseResponseCaching . Aplikace uživatelského rozhraní, jako Razor jsou stránky, obvykle nejsou užitečné, protože prohlížeče obvykle nastavují hlavičky požadavků, které brání ukládání do mezipaměti.
Ukládání výstupu do mezipaměti přináší výhody aplikací uživatelského rozhraní. |
Request Decompression | Poskytuje podporu pro dekompresi požadavků. | Před komponentami, které čtou text požadavku. |
Response Compression | Poskytuje podporu pro kompresi odpovědí. | Před komponentami, které vyžadují kompresi. |
Request Localization | Poskytuje podporu lokalizace. | Před komponentami citlivými na lokalizaci. Při použití RouteDataRequestCultureProvider musí následovat po middlewaru Routing. |
Endpoint Routing | Definuje a omezuje trasy požadavků. | Terminál pro vyhovující trasy. |
SPA | Zpracovává všechny požadavky od tohoto bodu v řetězci middlewaru vrácením výchozí stránky pro jednostránkovou aplikaci (SPA). | U konce řetězce, aby měl přednost ostatní middleware pro obsluhu statických souborů, akcí MVC atd. |
Relace | Poskytuje podporu pro správu uživatelských relací. | Před komponentami, které vyžadují middleware Session. |
Static Files | Poskytuje podporu pro obsluhu statických souborů a procházení adresářů. | Terminál, pokud požadavek odpovídá souboru. |
Přepsání adresy URL | Poskytuje podporu pro přepis adres URL a přesměrování požadavků. | Před komponentami, které využívají danou adresu URL. |
W3CLogging | Generuje protokoly přístupu k serveru v rozšířeném formátu souborů protokolu W3C. | Na začátku kanálu middlewaru. |
Webové sokety | Povoluje protokol WebSocket. | Před komponentami, které jsou potřeba k přijetí požadavků WebSocket. |
Autor: Rick Anderson a Steve Smith
Middleware je software sestavený do kanálu aplikace pro zpracování požadavků a odpovědí. Každá komponenta:
K sestavení kanálu požadavků se používají delegáti požadavků. Delegáti požadavků zpracovávají každý požadavek HTTP.
Delegáti požadavků se konfigurují pomocí rozšiřujících metod Run, Map a Use. Jednotlivý delegát požadavku může být zadán na řádku jako anonymní metoda (tzv. in-line middleware) nebo může být definován v opakovaně použitelné třídě. Tyto opakovaně použitelné třídy a vložené anonymní metody jsou middleware, označované také jako komponenty middlewaru. Každá komponenta middlewaru v kanálu požadavků zodpovídá za vyvolání další komponenty v kanálu nebo zkratování kanálu. Když middleware zkratuje, označuje se jako terminální middleware, protože brání dalšímu middlewaru ve zpracování požadavku.
Téma věnované migraci obslužných rutin HTTP a modulů do middlewaru ASP.NET Core vysvětluje rozdíl mezi kanály požadavků v prostředích ASP.NET Core a ASP.NET 4.x a poskytuje další ukázky middlewaru.
ASP.NET Core obsahuje celou řadu analyzátorů Compile Platform, které kontrolují kód aplikace z hlediska kvality. Další informace najdete v tématu Analýza kódu v aplikacích ASP.NET Core.
Kanál požadavků ASP.NET Core se skládá z posloupnosti delegátů požadavků, kteří se volají jeden po druhém. Tento koncept demonstruje následující schéma. Vlákno spouštění postupuje podle černých šipek.
Každý delegát může provádět operace před a za dalším delegátem. Delegáti zpracování výjimek by se měli volat v rané fázi zpracování kanálu, aby mohli zachytit výjimky, ke kterým dochází v pozdějších fázích zpracování kanálu.
Nejjednodušší možná aplikace ASP.NET Core nastavuje jednoho delegáta požadavků, který zpracovává všechny požadavky. Tento případ nezahrnuje vlastní kanál požadavků. Místo toho se jako reakce na každý požadavek HTTP volá jedna anonymní funkce.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Run(async context =>
{
await context.Response.WriteAsync("Hello world!");
});
app.Run();
Zřetězte několik delegátů požadavků společně s Use. Parametr next
představuje dalšího delegáta v kanálu. Kanál můžete zkratovat tak, že parametr next
. Obvykle můžete provádět akce před delegátem next
i po něm, jak ukazuje následující příklad:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Use(async (context, next) =>
{
// Do work that can write to the Response.
await next.Invoke();
// Do logging or other work that doesn't write to the Response.
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from 2nd delegate.");
});
app.Run();
Pokud delegát nepředá požadavek dalšímu delegátovi, označuje se to jako zkratování kanálu požadavků. Zkratování je často žádoucí, protože zabraňuje zbytečné práci. Například statický soubor middleware může fungovat jako terminálový middleware zpracováním požadavku na statický soubor a ukončením zbytku zpracování. Middleware přidaný do kanálu před middleware, který ukončí další zpracování, stále zpracovává kód po příslušných příkazech next.Invoke
. Ohledně pokusu o zápis do již odeslané odpovědi si však projděte následující upozornění.
Upozornění
Po odeslání odpovědi klientovi nevolejte next.Invoke
. Změny v HttpResponse po spuštění odpovědi vyvolají výjimku. Například nastavení hlaviček a stavového kódu vyvolá výjimku. Zápis do textu odpovědi po volání next
:
Content-Length
.HasStarted je užitečná nápověda indikující, jestli byly odeslány hlavičky nebo zapisováno do textu.
Delegáti Run neobdrží parametr next
. První delegát Run
je vždy terminální a ukončí kanál. Použití Run
je obvyklá konvence. Některé komponenty middlewaru můžou zpřístupnit metody Run[Middleware]
, které běží na konci kanálu:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Use(async (context, next) =>
{
// Do work that can write to the Response.
await next.Invoke();
// Do logging or other work that doesn't write to the Response.
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from 2nd delegate.");
});
app.Run();
Pokud chcete zobrazit komentáře ke kódu přeložené do jiných jazyků, než je angličtina, dejte nám vědět v této diskuzi na GitHubu.
V předchozím příkladu delegát Run
zapíše "Hello from 2nd delegate."
do odpovědi a pak ukončí kanál. Pokud je za delegáta Use
přidán jiný delegát Run
nebo Run
, nevolá se.
Rozšiřující metoda app.Use bez přidělování:
next
.Další informace najdete u tohoto problému na GitHubu.
Následující diagram znázorňuje kompletní kanál zpracování požadavků pro aplikace ASP.NET Core MVC a Razor Pages. Můžete si prohlédnout, jak je v typické aplikaci uspořádané stávající middlewary seřazené a kde se přidávají vlastní middlewary. Máte plnou kontrolu nad tím, jak změnit pořadí stávajících middlewarů nebo vložit nové vlastní middlewary podle potřeby vašich scénářů.
Middleware Endpoint v předchozím diagramu spustí kanál filtru pro odpovídající typ aplikace – MVC nebo Razor Pages.
Middleware Routing v předchozím diagramu je zobrazený za Static Files. Toto je pořadí, které šablony projektů implementují explicitním voláním app.UseRouting. Pokud nezavoláte app.UseRouting
, ve výchozím nastavení se middleware Routing spustí na začátku kanálu. Další informace najdete v tématu Směrování.
Pořadí, ve kterém jsou komponenty middlewaru přidány do souboru Program.cs
, definuje pořadí, ve kterém se komponenty middlewaru vyvolávají pro požadavky, a obrácené pořadí pro odpovědi. Toto pořadí má zásadní důležitost pro zabezpečení, výkon a funkce.
Následující zvýrazněný kód v Program.cs
přidává komponenty middlewaru související se zabezpečením v typickém doporučeném pořadí:
using IndividualAccountsExample.Data;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
// app.UseCookiePolicy();
app.UseRouting();
// app.UseRequestLocalization();
// app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
// app.UseSession();
// app.UseResponseCompression();
// app.UseResponseCaching();
app.MapRazorPages();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
V předchozím kódu:
UseCors
, UseAuthentication
a UseAuthorization
musí být v uvedeném pořadí.UseCors
musí aktuálně být před UseResponseCaching
. Tento požadavek je vysvětlený v problému s dotnet/aspnetcore #23218 na GitHubu.UseRequestLocalization
musí být uvedený před jakýmkoli jiným middlewarem, který kontroluje kulturu požadavků (například app.UseMvcWithDefaultRoute()
).V některých scénářích má middleware jiné řazení. Například pořadí ukládání do mezipaměti a komprese je specifické pro daný scénář a existuje několik platných pořadí. Příklad:
app.UseResponseCaching();
app.UseResponseCompression();
V předchozím kódu by bylo možné snížit využití procesoru uložením komprimované odpovědi do mezipaměti, ale mohlo by se stát, že budete ukládat do mezipaměti více reprezentací prostředku pomocí různých kompresních algoritmů, jako jsou například Gzip nebo Brotli.
Následující pořadí kombinuje statické soubory, aby se umožnilo ukládání komprimovaných statických souborů do mezipaměti:
app.UseResponseCaching();
app.UseResponseCompression();
app.UseStaticFiles();
Následující kód Program.cs
přidá komponenty middlewaru pro běžné scénáře aplikací:
Strict-Transport-Security
.if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.MapRazorPages();
V předchozím ukázkovém kódu je každá rozšiřující metoda middlewaru zpřístupněná v WebApplicationBuilder prostřednictvím oboru názvů Microsoft.AspNetCore.Builder.
UseExceptionHandler je první komponenta middlewaru přidaná do kanálu. Proto middleware Exception Handler zachycuje všechny výjimky, ke kterým dochází v pozdějších voláních.
Middleware Static File se volá v rané fázi zpracování kanálu, aby mohl zpracovávat požadavky a provést zkratování, aniž by se musely projít zbývající komponenty. Middleware Static File neposkytuje žádné kontroly autorizace. Všechny soubory obsluhované middlewarem Static File, včetně souborů pod wwwroot, jsou veřejně dostupné. Informace o přístupu k zabezpečení statických souborů najdete v tématu Statické soubory v ASP.NET Core.
Pokud požadavek nezpracuje middleware Static File, předá se do middlewaru Authentication (UseAuthentication), který provádí ověřování. Ověřování nezpůsobí zkratování neověřených požadavků. I když middleware Authentication ověřuje požadavky, autorizace (a zamítnutí) nastane až poté, co MVC vybere konkrétní kontroler MVC nebo Razor Pages a akci.
Následující příklad ukazuje pořadí middlewaru, ve kterém požadavky pro statické soubory zpracovává middleware Static File před middlewarem Response Compression. Statické soubory nejsou při tomto uspořádání middlewaru komprimovány. Odpovědi Razor Pages je možné komprimovat.
// Static files aren't compressed by Static File Middleware.
app.UseStaticFiles();
app.UseRouting();
app.UseResponseCompression();
app.MapRazorPages();
Informace o jednostránkových aplikacích najdete v průvodcích pro šablony projektů React a Angular.
Pořadí volání UseCors
a UseStaticFiles
závisí na aplikaci. Další informace najdete v tématu Pořadí UseCors a UseStaticFiles
Middleware Forwarded Headers by měl běžet před ostatním middlewarem. Toto řazení zajišťuje, že middleware, který spoléhá na informace předávaných hlaviček, může využívat hodnoty hlaviček ke zpracování. Pokud chcete middleware Forwarded Headers spustit po diagnostice a middlewaru pro zpracování chyb, přečtěte si téma Middleware Ordered Headers.
Rozšíření Map se používají jako konvence pro větvení kanálu.
Map
rozvětví kanál požadavku na základě shod dané cesty k požadavku. Pokud cesta k požadavku začíná danou cestou, větev se spustí.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Map("/map1", HandleMapTest1);
app.Map("/map2", HandleMapTest2);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
app.Run();
static void HandleMapTest1(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 1");
});
}
static void HandleMapTest2(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 2");
});
}
Následující tabulka ukazuje požadavky a odpovědi z http://localhost:1234
s využitím předchozího kódu.
Požádat | Response |
---|---|
localhost:1234 | Hello from non-Map delegate. |
localhost:1234/map1 | Map Test 1 |
localhost:1234/map2 | Map Test 2 |
localhost:1234/map3 | Hello from non-Map delegate. |
Při použití Map
se odpovídající segmenty cest odeberou z HttpRequest.Path
a připojí ke HttpRequest.PathBase
pro každý požadavek.
Map
podporuje vnoření, například:
app.Map("/level1", level1App => {
level1App.Map("/level2a", level2AApp => {
// "/level1/level2a" processing
});
level1App.Map("/level2b", level2BApp => {
// "/level1/level2b" processing
});
});
Map
také může odpovídat více segmentům najednou:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Map("/map1/seg1", HandleMultiSeg);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
app.Run();
static void HandleMultiSeg(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 1");
});
}
MapWhen rozvětví kanál požadavku na základě výsledku daného predikátu. K mapování požadavků na novou větev kanálu je možné použít jakýkoli predikát typu Func<HttpContext, bool>
. V následujícím příkladu se predikát používá ke zjištění přítomnosti proměnné řetězce dotazu branch
:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapWhen(context => context.Request.Query.ContainsKey("branch"), HandleBranch);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
app.Run();
static void HandleBranch(IApplicationBuilder app)
{
app.Run(async context =>
{
var branchVer = context.Request.Query["branch"];
await context.Response.WriteAsync($"Branch used = {branchVer}");
});
}
Následující tabulka ukazuje požadavky a odpovědi z http://localhost:1234
s využitím předchozího kódu:
Požádat | Response |
---|---|
localhost:1234 |
Hello from non-Map delegate. |
localhost:1234/?branch=main |
Branch used = main |
UseWhen také rozvětví kanál požadavku na základě výsledku daného predikátu. Na rozdíl od MapWhen
se tato větev znovu připojí k hlavnímu kanálu, pokud nezpůsobí zkratování nebo neobsahuje terminální middleware:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseWhen(context => context.Request.Query.ContainsKey("branch"),
appBuilder => HandleBranchAndRejoin(appBuilder));
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
app.Run();
void HandleBranchAndRejoin(IApplicationBuilder app)
{
var logger = app.ApplicationServices.GetRequiredService<ILogger<Program>>();
app.Use(async (context, next) =>
{
var branchVer = context.Request.Query["branch"];
logger.LogInformation("Branch used = {branchVer}", branchVer);
// Do work that doesn't write to the Response.
await next();
// Do other work that doesn't write to the Response.
});
}
V předchozím příkladu se pro všechny požadavky zapíše odpověď Hello from non-Map delegate.
. Pokud požadavek obsahuje proměnnou řetězce dotazu branch
, před opětovným připojením k hlavnímu kanálu se zaprotokoluje její hodnota.
ASP.NET Core se dodává s následujícími komponentami middlewaru. Sloupec Pořadí obsahuje poznámky k umístění middlewaru v kanálu zpracování požadavků a to, za jakých podmínek může middleware ukončit zpracování požadavků. Když middleware zkratuje kanál zpracování požadavků a zabrání dalšímu navazujícímu middlewaru zpracovat požadavek, označuje se jako terminální middleware. Další informace o zkratování najdete v části Vytvoření middlewarového kanálu s webapplication .
Middleware | Popis | Objednávka |
---|---|---|
Authentication | Poskytuje podporu ověřování. | Než je potřeba HttpContext.User . Terminál pro zpětné volání OAuth. |
Autorizace | Poskytuje podporu autorizace. | Okamžitě po middlewaru Authentication. |
Cookie Policy | Sleduje souhlas uživatelů s ukládáním osobních údajů a vynucuje minimální standardy pro pole cookie, například secure a SameSite . |
Než middleware vydá soubory cookie. Příklady: Authentication, Session, MVC (TempData). |
CORS | Konfiguruje sdílení prostředků mezi zdroji (CORS). | Před komponentami, které používají CORS.
UseCors v současné době musí předcházet před UseResponseCaching , a to kvůli této chybě. |
DeveloperExceptionPage | Vygeneruje stránku s informacemi o chybách, které jsou určené jenom pro použití ve vývojovém prostředí. | Před komponentami, které generují chyby. V případě vývojového prostředí šablony projektů automaticky zaregistrují tento middleware jako první middleware v kanálu. |
Diagnostika | Několik samostatných middlewarů, které poskytují stránku výjimek pro vývojáře, zpracování výjimek, stránky stavových kódů a výchozí webovou stránku pro nové aplikace. | Před komponentami, které generují chyby. Terminál pro výjimky nebo obsluhu výchozí webové stránky pro nové aplikace. |
Forwarded Headers | Předá přeposílané hlavičky do aktuálního požadavku. | Před komponentami, které využívají aktualizovaná pole. Příklady: Schéma, hostitel, IP adresa klienta, metoda. |
Health Check | Kontroluje stav aplikace ASP.NET Core a jejích závislostí, jako je kontrola dostupnosti databáze. | Terminál, pokud požadavek odpovídá koncovému bodu kontroly stavu. |
Header Propagation | Šíří hlavičky HTTP z příchozího požadavku do odchozích požadavků klienta HTTP. | |
Protokolování HTTP | Protokoluje požadavky HTTP a odpovědi. | Na začátku kanálu middlewaru. |
HTTP Method Override | Umožňuje, aby příchozí požadavek POST přepsal metodu. | Před komponentami, které využívají aktualizovanou metodu. |
HTTPS Redirection | Přesměruje všechny požadavky HTTP na HTTPS. | Před komponentami, které využívají danou adresu URL. |
HTTP Strict Transport Security (HSTS) | Middleware pro vylepšení zabezpečení, který přidává speciální hlavičku odpovědi. | Před odesláním odpovědí a po komponentách, které upravují požadavky. Příklady: Přeposílané hlavičky, přepsání adresy URL. |
MVC | Zpracovává požadavky s využitím MVC / Razor Pages. | Terminál, pokud požadavek odpovídá trase. |
OWIN | Spolupracuje s aplikacemi, servery a middlewarem založenými na OWIN. | Terminál, pokud middleware OWIN plně zpracuje daný požadavek. |
Request Decompression | Poskytuje podporu pro dekompresi požadavků. | Před komponentami, které čtou text požadavku. |
Ukládání odpovědí do mezipaměti | Poskytuje podporu pro ukládání odpovědí do mezipaměti. | Před komponentami, které vyžadují ukládání do mezipaměti. Je potřeba použít UseCORS před UseResponseCaching . |
Response Compression | Poskytuje podporu pro kompresi odpovědí. | Před komponentami, které vyžadují kompresi. |
Request Localization | Poskytuje podporu lokalizace. | Před komponentami citlivými na lokalizaci. Při použití RouteDataRequestCultureProvider musí následovat po middlewaru Routing. |
Endpoint Routing | Definuje a omezuje trasy požadavků. | Terminál pro vyhovující trasy. |
SPA | Zpracovává všechny požadavky od tohoto bodu v řetězci middlewaru vrácením výchozí stránky pro jednostránkovou aplikaci (SPA). | U konce řetězce, aby měl přednost ostatní middleware pro obsluhu statických souborů, akcí MVC atd. |
Relace | Poskytuje podporu pro správu uživatelských relací. | Před komponentami, které vyžadují middleware Session. |
Static Files | Poskytuje podporu pro obsluhu statických souborů a procházení adresářů. | Terminál, pokud požadavek odpovídá souboru. |
Přepsání adresy URL | Poskytuje podporu pro přepis adres URL a přesměrování požadavků. | Před komponentami, které využívají danou adresu URL. |
W3CLogging | Generuje protokoly přístupu k serveru v rozšířeném formátu souborů protokolu W3C. | Na začátku kanálu middlewaru. |
Webové sokety | Povoluje protokol WebSocket. | Před komponentami, které jsou potřeba k přijetí požadavků WebSocket. |
Autor: Rick Anderson a Steve Smith
Middleware je software sestavený do kanálu aplikace pro zpracování požadavků a odpovědí. Každá komponenta:
K sestavení kanálu požadavků se používají delegáti požadavků. Delegáti požadavků zpracovávají každý požadavek HTTP.
Delegáti požadavků se konfigurují pomocí rozšiřujících metod Run, Map a Use. Jednotlivý delegát požadavku může být zadán na řádku jako anonymní metoda (tzv. in-line middleware) nebo může být definován v opakovaně použitelné třídě. Tyto opakovaně použitelné třídy a vložené anonymní metody jsou middleware, označované také jako komponenty middlewaru. Každá komponenta middlewaru v kanálu požadavků zodpovídá za vyvolání další komponenty v kanálu nebo zkratování kanálu. Když middleware zkratuje, označuje se jako terminální middleware, protože brání dalšímu middlewaru ve zpracování požadavku.
Téma věnované migraci obslužných rutin HTTP a modulů do middlewaru ASP.NET Core vysvětluje rozdíl mezi kanály požadavků v prostředích ASP.NET Core a ASP.NET 4.x a poskytuje další ukázky middlewaru.
Kanál požadavků ASP.NET Core se skládá z posloupnosti delegátů požadavků, kteří se volají jeden po druhém. Tento koncept demonstruje následující schéma. Vlákno spouštění postupuje podle černých šipek.
Každý delegát může provádět operace před a za dalším delegátem. Delegáti zpracování výjimek by se měli volat v rané fázi zpracování kanálu, aby mohli zachytit výjimky, ke kterým dochází v pozdějších fázích zpracování kanálu.
Nejjednodušší možná aplikace ASP.NET Core nastavuje jednoho delegáta požadavků, který zpracovává všechny požadavky. Tento případ nezahrnuje vlastní kanál požadavků. Místo toho se jako reakce na každý požadavek HTTP volá jedna anonymní funkce.
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Hello, World!");
});
}
}
Zřetězte několik delegátů požadavků společně s Use. Parametr next
představuje dalšího delegáta v kanálu. Kanál můžete zkratovat tak, že nevoláte parametr next. Obvykle můžete provádět akce před dalším delegátem i po něm, jak ukazuje následující příklad:
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
// Do work that doesn't write to the Response.
await next.Invoke();
// Do logging or other work that doesn't write to the Response.
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from 2nd delegate.");
});
}
}
Pokud delegát nepředá požadavek dalšímu delegátovi, označuje se to jako zkratování kanálu požadavků. Zkratování je často žádoucí, protože zabraňuje zbytečné práci. Například Middleware statického souboru může fungovat jako terminálový middleware zpracováním požadavku na statický soubor a zkratováním zbytku potrubí. Middleware přidaný do kanálu před middleware, který ukončí další zpracování, stále zpracovává kód po příslušných příkazech next.Invoke
. Ohledně pokusu o zápis do již odeslané odpovědi si však projděte následující upozornění.
Upozornění
Po odeslání odpovědi klientovi nevolejte next.Invoke
. Změny v HttpResponse po spuštění odpovědi vyvolají výjimku. Například nastavení hlaviček a stavového kódu vyvolá výjimku. Zápis do textu odpovědi po volání next
:
Content-Length
.HasStarted je užitečná nápověda indikující, jestli byly odeslány hlavičky nebo zapisováno do textu.
Delegáti Run neobdrží parametr next
. První delegát Run
je vždy terminální a ukončí kanál. Použití Run
je obvyklá konvence. Některé komponenty middlewaru můžou zpřístupnit metody Run[Middleware]
, které běží na konci kanálu:
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
// Do work that doesn't write to the Response.
await next.Invoke();
// Do logging or other work that doesn't write to the Response.
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from 2nd delegate.");
});
}
}
Pokud chcete zobrazit komentáře ke kódu přeložené do jiných jazyků, než je angličtina, dejte nám vědět v této diskuzi na GitHubu.
V předchozím příkladu delegát Run
zapíše "Hello from 2nd delegate."
do odpovědi a pak ukončí kanál. Pokud je za delegáta Use
přidán jiný delegát Run
nebo Run
, nevolá se.
Následující diagram znázorňuje kompletní kanál zpracování požadavků pro aplikace ASP.NET Core MVC a Razor Pages. Můžete si prohlédnout, jak je v typické aplikaci uspořádané stávající middlewary seřazené a kde se přidávají vlastní middlewary. Máte plnou kontrolu nad tím, jak změnit pořadí stávajících middlewarů nebo vložit nové vlastní middlewary podle potřeby vašich scénářů.
Middleware Endpoint v předchozím diagramu spustí kanál filtru pro odpovídající typ aplikace – MVC nebo Razor Pages.
Pořadí, ve kterém jsou komponenty middlewaru přidány do metody Startup.Configure
, definuje pořadí, ve kterém se komponenty middlewaru vyvolávají pro požadavky, a obrácené pořadí pro odpovědi. Toto pořadí má zásadní důležitost pro zabezpečení, výkon a funkce.
Následující metoda Startup.Configure
přidává komponenty middlewaru související se zabezpečením v typickém doporučeném pořadí:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
// app.UseCookiePolicy();
app.UseRouting();
// app.UseRequestLocalization();
// app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
// app.UseSession();
// app.UseResponseCompression();
// app.UseResponseCaching();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
V předchozím kódu:
UseCors
, UseAuthentication
a UseAuthorization
musí být v uvedeném pořadí.UseCors
v současné době musí předcházet před UseResponseCaching
, a to kvůli této chybě.UseRequestLocalization
musí být uvedený před jakýmkoli jiným middlewarem, který kontroluje kulturu požadavků (například app.UseMvcWithDefaultRoute()
).V některých scénářích má middleware jiné řazení. Například pořadí ukládání do mezipaměti a komprese je specifické pro daný scénář a existuje několik platných pořadí. Příklad:
app.UseResponseCaching();
app.UseResponseCompression();
V předchozím kódu by bylo možné snížit využití procesoru uložením komprimované odpovědi do mezipaměti, ale mohlo by se stát, že budete ukládat do mezipaměti více reprezentací prostředku pomocí různých kompresních algoritmů, jako jsou například Gzip nebo Brotli.
Následující pořadí kombinuje statické soubory, aby se umožnilo ukládání komprimovaných statických souborů do mezipaměti:
app.UseResponseCaching();
app.UseResponseCompression();
app.UseStaticFiles();
Následující metoda Startup.Configure
přidá komponenty middlewaru pro běžné scénáře aplikací:
Strict-Transport-Security
.public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
V předchozím ukázkovém kódu je každá rozšiřující metoda middlewaru zpřístupněná v IApplicationBuilder prostřednictvím oboru názvů Microsoft.AspNetCore.Builder.
UseExceptionHandler je první komponenta middlewaru přidaná do kanálu. Proto middleware Exception Handler zachycuje všechny výjimky, ke kterým dochází v pozdějších voláních.
Middleware Static File se volá v rané fázi zpracování kanálu, aby mohl zpracovávat požadavky a provést zkratování, aniž by se musely projít zbývající komponenty. Middleware Static File neposkytuje žádné kontroly autorizace. Všechny soubory obsluhované middlewarem Static File, včetně souborů pod wwwroot, jsou veřejně dostupné. Informace o přístupu k zabezpečení statických souborů najdete v tématu Statické soubory v ASP.NET Core.
Pokud požadavek nezpracuje middleware Static File, předá se do middlewaru Authentication (UseAuthentication), který provádí ověřování. Ověřování nezpůsobí zkratování neověřených požadavků. I když middleware Authentication ověřuje požadavky, autorizace (a zamítnutí) nastane až poté, co MVC vybere konkrétní kontroler MVC nebo Razor Pages a akci.
Následující příklad ukazuje pořadí middlewaru, ve kterém požadavky pro statické soubory zpracovává middleware Static File před middlewarem Response Compression. Statické soubory nejsou při tomto uspořádání middlewaru komprimovány. Odpovědi Razor Pages je možné komprimovat.
public void Configure(IApplicationBuilder app)
{
// Static files aren't compressed by Static File Middleware.
app.UseStaticFiles();
app.UseRouting();
app.UseResponseCompression();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
Pro jednostránkové aplikace (SPA) je middleware SPA UseSpaStaticFiles obvykle v kanálu middlewaru poslední. Middleware SPA je poslední:
Další podrobnosti o jednostránkových aplikacích najdete v průvodcích pro šablony projektů React a Angular.
Middleware Forwarded Headers by měl běžet před ostatním middlewarem. Toto řazení zajišťuje, že middleware, který spoléhá na informace předávaných hlaviček, může využívat hodnoty hlaviček ke zpracování. Pokud chcete middleware Forwarded Headers spustit po diagnostice a middlewaru pro zpracování chyb, přečtěte si téma Middleware Ordered Headers.
Rozšíření Map se používají jako konvence pro větvení kanálu.
Map
rozvětví kanál požadavku na základě shod dané cesty k požadavku. Pokud cesta k požadavku začíná danou cestou, větev se spustí.
public class Startup
{
private static void HandleMapTest1(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 1");
});
}
private static void HandleMapTest2(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 2");
});
}
public void Configure(IApplicationBuilder app)
{
app.Map("/map1", HandleMapTest1);
app.Map("/map2", HandleMapTest2);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
}
}
Následující tabulka ukazuje požadavky a odpovědi z http://localhost:1234
s využitím předchozího kódu.
Požádat | Response |
---|---|
localhost:1234 | Hello from non-Map delegate. |
localhost:1234/map1 | Map Test 1 |
localhost:1234/map2 | Map Test 2 |
localhost:1234/map3 | Hello from non-Map delegate. |
Při použití Map
se odpovídající segmenty cest odeberou z HttpRequest.Path
a připojí ke HttpRequest.PathBase
pro každý požadavek.
Map
podporuje vnoření, například:
app.Map("/level1", level1App => {
level1App.Map("/level2a", level2AApp => {
// "/level1/level2a" processing
});
level1App.Map("/level2b", level2BApp => {
// "/level1/level2b" processing
});
});
Map
také může odpovídat více segmentům najednou:
public class Startup
{
private static void HandleMultiSeg(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map multiple segments.");
});
}
public void Configure(IApplicationBuilder app)
{
app.Map("/map1/seg1", HandleMultiSeg);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
}
}
MapWhen rozvětví kanál požadavku na základě výsledku daného predikátu. K mapování požadavků na novou větev kanálu je možné použít jakýkoli predikát typu Func<HttpContext, bool>
. V následujícím příkladu se predikát používá ke zjištění přítomnosti proměnné řetězce dotazu branch
:
public class Startup
{
private static void HandleBranch(IApplicationBuilder app)
{
app.Run(async context =>
{
var branchVer = context.Request.Query["branch"];
await context.Response.WriteAsync($"Branch used = {branchVer}");
});
}
public void Configure(IApplicationBuilder app)
{
app.MapWhen(context => context.Request.Query.ContainsKey("branch"),
HandleBranch);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
}
}
Následující tabulka ukazuje požadavky a odpovědi z http://localhost:1234
s využitím předchozího kódu:
Požádat | Response |
---|---|
localhost:1234 | Hello from non-Map delegate. |
localhost:1234/?branch=main | Branch used = main |
UseWhen také rozvětví kanál požadavku na základě výsledku daného predikátu. Na rozdíl od MapWhen
se tato větev znovu připojí k hlavnímu kanálu, pokud nezpůsobí zkratování nebo neobsahuje terminální middleware:
public class Startup
{
private void HandleBranchAndRejoin(IApplicationBuilder app, ILogger<Startup> logger)
{
app.Use(async (context, next) =>
{
var branchVer = context.Request.Query["branch"];
logger.LogInformation("Branch used = {branchVer}", branchVer);
// Do work that doesn't write to the Response.
await next();
// Do other work that doesn't write to the Response.
});
}
public void Configure(IApplicationBuilder app, ILogger<Startup> logger)
{
app.UseWhen(context => context.Request.Query.ContainsKey("branch"),
appBuilder => HandleBranchAndRejoin(appBuilder, logger));
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from main pipeline.");
});
}
}
V předchozím příkladu se pro všechny požadavky zapíše odpověď Hello from main pipeline. Pokud požadavek obsahuje proměnnou řetězce dotazu branch
, před opětovným připojením k hlavnímu kanálu se zaprotokoluje její hodnota.
ASP.NET Core se dodává s následujícími komponentami middlewaru. Sloupec Pořadí obsahuje poznámky k umístění middlewaru v kanálu zpracování požadavků a to, za jakých podmínek může middleware ukončit zpracování požadavků. Když middleware zkratuje kanál zpracování požadavků a zabrání dalšímu navazujícímu middlewaru zpracovat požadavek, označuje se jako terminální middleware. Další informace o zkratování najdete v části Vytvoření kanálu middlewaru s využitím IApplicationBuilderu.
Middleware | Popis | Objednávka |
---|---|---|
Authentication | Poskytuje podporu ověřování. | Než je potřeba HttpContext.User . Terminál pro zpětné volání OAuth. |
Autorizace | Poskytuje podporu autorizace. | Okamžitě po middlewaru Authentication. |
Cookie Policy | Sleduje souhlas uživatelů s ukládáním osobních údajů a vynucuje minimální standardy pro pole cookie, například secure a SameSite . |
Než middleware vydá soubory cookie. Příklady: Authentication, Session, MVC (TempData). |
CORS | Konfiguruje sdílení prostředků mezi zdroji (CORS). | Před komponentami, které používají CORS.
UseCors v současné době musí předcházet před UseResponseCaching , a to kvůli této chybě. |
Diagnostika | Několik samostatných middlewarů, které poskytují stránku výjimek pro vývojáře, zpracování výjimek, stránky stavových kódů a výchozí webovou stránku pro nové aplikace. | Před komponentami, které generují chyby. Terminál pro výjimky nebo obsluhu výchozí webové stránky pro nové aplikace. |
Forwarded Headers | Předá přeposílané hlavičky do aktuálního požadavku. | Před komponentami, které využívají aktualizovaná pole. Příklady: Schéma, hostitel, IP adresa klienta, metoda. |
Health Check | Kontroluje stav aplikace ASP.NET Core a jejích závislostí, jako je kontrola dostupnosti databáze. | Terminál, pokud požadavek odpovídá koncovému bodu kontroly stavu. |
Header Propagation | Šíří hlavičky HTTP z příchozího požadavku do odchozích požadavků klienta HTTP. | |
HTTP Method Override | Umožňuje, aby příchozí požadavek POST přepsal metodu. | Před komponentami, které využívají aktualizovanou metodu. |
HTTPS Redirection | Přesměruje všechny požadavky HTTP na HTTPS. | Před komponentami, které využívají danou adresu URL. |
HTTP Strict Transport Security (HSTS) | Middleware pro vylepšení zabezpečení, který přidává speciální hlavičku odpovědi. | Před odesláním odpovědí a po komponentách, které upravují požadavky. Příklady: Přeposílané hlavičky, přepsání adresy URL. |
MVC | Zpracovává požadavky s využitím MVC / Razor Pages. | Terminál, pokud požadavek odpovídá trase. |
OWIN | Spolupracuje s aplikacemi, servery a middlewarem založenými na OWIN. | Terminál, pokud middleware OWIN plně zpracuje daný požadavek. |
Ukládání odpovědí do mezipaměti | Poskytuje podporu pro ukládání odpovědí do mezipaměti. | Před komponentami, které vyžadují ukládání do mezipaměti. Je potřeba použít UseCORS před UseResponseCaching . |
Response Compression | Poskytuje podporu pro kompresi odpovědí. | Před komponentami, které vyžadují kompresi. |
Request Localization | Poskytuje podporu lokalizace. | Před komponentami citlivými na lokalizaci. Při použití RouteDataRequestCultureProvider musí následovat po middlewaru Routing. |
Endpoint Routing | Definuje a omezuje trasy požadavků. | Terminál pro vyhovující trasy. |
SPA | Zpracovává všechny požadavky od tohoto bodu v řetězci middlewaru vrácením výchozí stránky pro jednostránkovou aplikaci (SPA). | U konce řetězce, aby měl přednost ostatní middleware pro obsluhu statických souborů, akcí MVC atd. |
Relace | Poskytuje podporu pro správu uživatelských relací. | Před komponentami, které vyžadují middleware Session. |
Static Files | Poskytuje podporu pro obsluhu statických souborů a procházení adresářů. | Terminál, pokud požadavek odpovídá souboru. |
Přepsání adresy URL | Poskytuje podporu pro přepis adres URL a přesměrování požadavků. | Před komponentami, které využívají danou adresu URL. |
Webové sokety | Povoluje protokol WebSocket. | Před komponentami, které jsou potřeba k přijetí požadavků WebSocket. |
Zpětná vazba k produktu ASP.NET Core
ASP.NET Core je open source projekt. Vyberte odkaz pro poskytnutí zpětné vazby:
Události
Mistrovství Světa v Power BI DataViz
14. 2. 16 - 31. 3. 16
Se 4 šance na vstup, můžete vyhrát konferenční balíček a udělat to na LIVE Grand Finale v Las Vegas
Další informaceŠkolení
Modul
Přizpůsobení chování ASP.NET Core pomocí middlewaru - Training
Principy a implementace middlewaru v aplikaci ASP.NET Core Použijte zahrnutý middleware, jako je protokolování HTTP a ověřování. Vytvořte vlastní middleware pro zpracování požadavků a odpovědí.