Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu .NET 9.
Ostrzeżenie
Ta wersja ASP.NET Core nie jest już obsługiwana. Aby uzyskać więcej informacji, zobacz zasady pomocy technicznej platformy .NET i platformy .NET Core. Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu dla platformy .NET 9.
Ważne
Te informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany, zanim zostanie wydany komercyjnie. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
Oprogramowanie pośredniczące to oprogramowanie, które jest wmontowane w potok aplikacji w celu obsługi żądań i odpowiedzi. Każdy składnik:
Określa, czy przekazać dalej żądanie do następnego składnika w potoku.
Może wykonywać pracę przed i po następnym elemencie w przepływie pracy.
Delegaci żądań są używani do kompilowania potoku żądania. Delegaci żądań obsługują każde żądanie HTTP.
Delegaci żądań są konfigurowani przy użyciu metod rozszerzeń Run, Map i Use. Pojedynczego delegata żądania można określić śródwierszowo jako metodę anonimową (nazywaną śródwierszowym oprogramowaniem pośredniczącym) lub można go zdefiniować w klasie wielokrotnego użytku. Te klasy wielokrotnego użytku i anonimowe funkcje w linii to oprogramowanie pośredniczące, nazywane również składnikami oprogramowania pośredniczącego. Każdy komponent pośredniczący w potoku żądania jest odpowiedzialny za wywoływanie następnego komponentu w potoku lub przerwanie działania potoku. Gdy oprogramowanie pośredniczące zatrzymuje się, jest ono nazywane końcowym oprogramowaniem pośredniczącym, ponieważ zapobiega dalszemu przetwarzaniu żądania przez oprogramowanie pośredniczące.
Rola oprogramowania pośredniczącego według typu aplikacji
Blazor Web Apps, Razor Pages oraz MVC przetwarzają żądania przeglądarki na serwerze przy użyciu middleware. Wskazówki zawarte w tym artykule dotyczą tych typów aplikacji.
Autonomiczne aplikacje Blazor WebAssembly są uruchamiane w całości na kliencie i nie przetwarzają żądań przy użyciu kanału oprogramowania pośredniczącego. Wskazówki zawarte w tym artykule nie dotyczą autonomicznych aplikacji Blazor WebAssembly.
Analiza kodu oprogramowania pośredniczącego
Platforma ASP.NET Core zawiera wiele analizatorów platformy kompilatora, które sprawdzają kod aplikacji pod kątem jakości. Aby uzyskać więcej informacji, zobacz Analiza kodu w aplikacjach platformy ASP.NET Core
Utwórz potok oprogramowania pośredniczącego za pomocą WebApplication
Potok przetwarzania żądań w ASP.NET Core składa się z sekwencji delegatów żądań, wywoływanych jeden po drugim. Na poniższym diagramie przedstawiono tę koncepcję. Przebieg wykonywania przebiega zgodnie z czarnymi strzałkami.
Każdy delegat może wykonywać operacje przed następnym delegatem i po nim. Delegaci obsługujący wyjątki powinni być wywoływani na wczesnym etapie w potoku, aby mogli przechwytywać wyjątki występujące w późniejszych etapach potoku.
Najprostsza możliwa aplikacja platformy ASP.NET Core konfiguruje jednego delegata żądania, który obsługuje wszystkie żądania. Ta sytuacja nie obejmuje rzeczywistego potoku przetwarzania żądania. Zamiast tego w odpowiedzi na każde żądanie HTTP jest wywoływana jedna funkcja anonimowa.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Run(async context =>
{
await context.Response.WriteAsync("Hello world!");
});
app.Run();
Połącz wiele delegatów żądań razem za pomocą funkcji Use. Parametr next reprezentuje następnego delegata w potoku. Można przerwać działanie potoku, nie wywołując parametr next. Zazwyczaj można wykonywać akcje zarówno przed delegatem next, jak i po nim, jak pokazano w poniższym przykładzie:
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();
Zwarcie potoku żądania
Gdy delegat nie przekazuje żądania do następnego delegata, jest to nazywane przerywaniem potoku żądania. Krótkie zwarcie jest często pożądane, ponieważ pozwala uniknąć niepotrzebnej pracy. Na przykład statyczne oprogramowanie pośredniczące plików może działać jako oprogramowanie pośredniczące terminalu, przetwarzając żądanie dotyczące pliku statycznego i zwarcie pozostałej części potoku. Oprogramowanie pośredniczące dodane do potoku przed oprogramowaniem pośredniczącym, które przerywa dalsze przetwarzanie, nadal przetwarza kod po instrukcjach next.Invoke. Niemniej jednak, zapoznaj się z następującym ostrzeżeniem dotyczącym próby zapisania w odpowiedzi, która została już wysłana.
Ostrzeżenie
Nie wywołuj next.Invoke podczas lub po wysłaniu odpowiedzi do klienta. Po rozpoczęciu HttpResponse, wszelkie zmiany powodują wyjątek. Na przykład ustawienie nagłówków i kodu stanu zgłasza wyjątek po rozpoczęciu odpowiedzi. Zapisywanie w treści odpowiedzi po wywołaniu komponentu next:
Może spowodować naruszenie protokołu, na przykład zapisanie większej ilości niż przewidziano Content-Length.
Może uszkodzić format treści, taki jak zapisanie stopki HTML w pliku CSS.
HasStarted to przydatna wskazówka informująca, czy nagłówki zostały wysłane lub treść została zapisana.
Delegaci Run nie otrzymują parametru next. Pierwszy delegat Run jest zawsze końcowy i kończy potok.
Run to konwencja. Niektóre składniki oprogramowania pośredniczącego mogą uwidaczniać metody Run[Middleware] uruchamiane na końcu potoku:
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();
W poprzednim przykładzie delegat Run zapisuje "Hello from 2nd delegate." w odpowiedzi, a następnie przerywa potok. Jeśli inny delegat Use lub Run zostanie dodany po delegacie Run, nie będzie on wywoływany.
Preferuj przeciążenie app.Use, które wymaga przekazania kontekstu do parametru 'next'
Metoda rozszerzenia nieprzydzielająca zasobów app.Use:
Wymaga przekazania kontekstu do składnika next.
Eliminuje dwie wewnętrzne alokacje per-request, które są konieczne podczas korzystania z innego wariantu przeciążenia.
Aby uzyskać więcej informacji, zobacz ten problem w serwisie GitHub.
Kolejność oprogramowania pośredniczącego
Na poniższym diagramie przedstawiono kompletny potok przetwarzania żądania dla aplikacji MVC i Razor Pages na platformie ASP.NET Core. Można zobaczyć, jak w typowej aplikacji uporządkowane są istniejące middleware oraz gdzie dodaje się niestandardowe middleware. Masz pełną kontrolę nad tym, jak zmienić kolejność istniejących oprogramowań pośredniczących lub wstrzyknąć nowe niestandardowe oprogramowania pośredniczące odpowiednio do potrzeb w scenariuszach.
Oprogramowanie middlewarowe punktu końcowego na wcześniejszym diagramie wykonuje przepływ filtracyjny dla odpowiedniego typu aplikacji — MVC lub Razor Strony.
Na powyższym diagramie jest przedstawione oprogramowanie pośredniczące Routing, które następuje po oprogramowaniu Pliki statyczne. Jest to kolejność implementowana w szablonach projektów przez jawne wywoływanie funkcji app.UseRouting. Jeśli nie wywołasz app.UseRouting, oprogramowanie pośredniczące Routing będzie domyślnie uruchamiane na początku procesu. Aby uzyskać więcej informacji, zobacz Routing.
Kolejność dodawania składników oprogramowania pośredniczącego w pliku Program.cs definiuje kolejność wywoływania składników oprogramowania pośredniczącego w żądaniach oraz odwrotną kolejność dla odpowiedzi. Kolejność ma kluczowe znaczenie dla bezpieczeństwa, wydajności i funkcjonalności.
Poniższy wyróżniony kod w programie Program.cs dodaje składniki oprogramowania pośredniczącego związane z zabezpieczeniami w typowej zalecanej kolejności:
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();
W poprzednim kodzie:
Oprogramowanie pośredniczące, które nie jest dodawane podczas tworzenia nowej aplikacji internetowej z kontami poszczególnych użytkowników, jest zakomentowane.
Nie każde oprogramowanie pośredniczące pojawia się w tej dokładnej kolejności, ale wiele tak. Na przykład:
UseCors, UseAuthentication i UseAuthorization muszą pojawić się w pokazanej kolejności.
UseRequestLocalization musi pojawić się przed wszelkim oprogramowaniem pośredniczącym, które może sprawdzać kulturę żądania, na przykład app.UseStaticFiles().
UseRateLimiter należy wywołać po UseRouting użyciu interfejsów API specyficznych dla punktu końcowego ograniczania szybkości. Na przykład, jeśli używany jest atrybut [EnableRateLimiting], UseRateLimiter musi być wywołany po UseRouting. Podczas wywoływania tylko globalnych ograniczników, UseRateLimiter można wywołać przed UseRouting.
W niektórych scenariuszach oprogramowanie pośredniczące ma inne określanie kolejności. Na przykład określanie kolejności buforowania i kompresji jest specyficzne dla scenariusza i istnieje wiele prawidłowych określeń kolejności. Na przykład:
W poprzednim kodzie użycie procesora CPU może zostać zmniejszone przez buforowanie skompresowanej odpowiedzi, ale może to doprowadzić do buforowania wielu reprezentacji zasobu przy użyciu różnych algorytmów kompresji, takich jak Gzip lub Brotli.
Poniższe określanie kolejności łączy pliki statyczne w celu umożliwienia buforowania skompresowanych plików statycznych:
Oprogramowanie pośredniczące plików statycznych (UseStaticFiles) zwraca pliki statyczne i przerywa dalsze przetwarzanie żądania.
Polityka Middleware (Cookie) (UseCookiePolicy) zapewnia zgodność aplikacji z rozporządzeniem o ochronie danych (RODO) w UE.
Oprogramowanie pośredniczące do routingu (UseRouting) do trasowania żądań.
Oprogramowanie pośredniczące uwierzytelniania (UseAuthentication) próbuje uwierzytelnić użytkownika przed zezwoleniem mu na uzyskiwanie dostępu do bezpiecznych zasobów.
Oprogramowanie pośredniczące autoryzacji (UseAuthorization) autoryzuje użytkownika do uzyskiwania dostępu do bezpiecznych zasobów.
Oprogramowanie pośredniczące sesji (UseSession) ustanawia i utrzymuje stan sesji. Jeśli aplikacja używa stanu sesji, wywołaj oprogramowanie pośredniczące sesji po oprogramowaniu pośredniczącym zasad dotyczących plików Cookie i przed oprogramowaniem pośredniczącym MVC.
Oprogramowanie pośredniczące do routingu punktów końcowych (UseEndpoints z MapRazorPages) służące do dodawania punktów końcowych Razor Pages do potoku żądania.
W poprzednim kodzie przykładowym każda metoda rozszerzenia oprogramowania pośredniczącego jest uwidoczniona w składniku WebApplicationBuilder za pośrednictwem przestrzeni nazw Microsoft.AspNetCore.Builder.
UseExceptionHandler to pierwszy składnik oprogramowania pośredniczącego dodany do potoku. Dlatego też oprogramowanie pośredniczące obsługi wyjątków przechwytuje wszelkie wyjątki, które występują w późniejszych wywołaniach.
Oprogramowanie pośredniczące do obsługi plików statycznych jest wywoływane na początku potoku, aby mogło obsługiwać żądania i przerywać ich przetwarzanie bez przechodzenia przez pozostałe składniki. Oprogramowanie pośredniczące plików statycznych nie przeprowadza kontroli autoryzacji. Wszystkie pliki obsługiwane przez oprogramowanie pośredniczące plików statycznych, w tym te w katalogu wwwroot, są publicznie dostępne. Aby poznać metodę zabezpieczania plików statycznych, zobacz Pliki statyczne na platformie ASP.NET Core.
Jeśli żądanie nie jest obsługiwane przez oprogramowanie pośredniczące plików statycznych, jest przekazywane do oprogramowania pośredniczącego uwierzytelniania (UseAuthentication), które wykonuje uwierzytelnianie. Uwierzytelnianie nie przerywa żądań nieuwierzytelnionych. Mimo że oprogramowanie pośredniczące uwierzytelniania uwierzytelnia żądania, autoryzacja (i odrzucenie) występuje dopiero po tym, jak MVC wybierze określoną stronę Razor lub kontroler MVC i akcję.
W poniższym przykładzie pokazano kolejność oprogramowania pośredniczącego, w której żądania dotyczące plików statycznych są obsługiwane przez oprogramowanie pośredniczące plików statycznych przed oprogramowaniem pośredniczącym kompresji odpowiedzi. Pliki statyczne nie są kompresowane w ramach tej kolejności oprogramowania pośredniczącego. Odpowiedzi Razor Pages można skompresować.
Kolejność wywoływania składników UseCors i UseStaticFiles zależy od aplikacji. Aby uzyskać więcej informacji, zobacz Kolejność UseCors i UseStaticFiles
Kolejność modułu "Forwarded Headers Middleware"
Oprogramowanie pośredniczące przekazanych nagłówków powinno być uruchamiane przed innymi oprogramowaniami pośredniczącymi. Ustalenie tej kolejności gwarantuje, że middleware opierające się na informacjach z przekazanych nagłówków może korzystać z wartości nagłówków do przetwarzania. Aby uruchomić oprogramowanie pośredniczące przekazanych nagłówków po oprogramowaniu pośredniczącym diagnostyki i obsługi błędów, zobacz Kolejność oprogramowania pośredniczącego przekazanych nagłówków.
Rozgałęzianie kanału oprogramowania pośredniego
Rozszerzenia Map są używane jako standard do rozgałęziania procesu. Element Map rozgałęzia potok żądania na podstawie dopasowań podanej ścieżki żądania. Jeśli ścieżka żądania rozpoczyna się od podanej ścieżki, wykonywane jest rozgałęzianie.
W poniższej tabeli przedstawiono żądania i odpowiedzi z adresu http://localhost:1234 przy użyciu poprzedzającego kodu.
Zażądaj
Odpowiedź
localhost:1234
Witaj od delegata nie-Mapy.
localhost:1234/map1
Test mapy 1
localhost:1234/map2
Test mapy 2
localhost:1234/map3
Witaj od delegata spoza Mapy.
Gdy jest używany składnik Map, dopasowane segmenty ścieżki są usuwane ze składnika HttpRequest.Path i dołączane do składnika HttpRequest.PathBase dla każdego żądania.
Komponent Map obsługuje zagnieżdżanie, na przykład:
Składnik Map może również jednocześnie pasować do wielu segmentów:
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 rozgałęzia potok żądania w oparciu o wynik danego predykatu. Dowolny predykat typu Func<HttpContext, bool> może zostać użyty do mapowania żądań na nową gałąź potoku. W poniższym przykładzie predykat jest używany do wykrywania obecności zmiennej ciągu zapytania 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}");
});
}
W poniższej tabeli przedstawiono żądania i odpowiedzi z adresu http://localhost:1234 przy użyciu poprzedniego kodu:
Zażądaj
Odpowiedź
localhost:1234
Hello from non-Map delegate.
localhost:1234/?branch=main
Branch used = main
Instrukcja UseWhen rozgałęzia także potok żądania na podstawie wyniku danego predykatu. W przeciwieństwie do MapWhen, ta gałąź jest ponownie łączona do głównej rury, jeśli nie zawiera middleware terminalnego.
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.
});
}
W poprzednim przykładzie dla wszystkich żądań jest pisana odpowiedź Hello from non-Map delegate.. Jeśli żądanie zawiera zmienną parametru zapytania branch, jego wartość jest rejestrowana przed ponownym dołączeniem do potoku głównego.
Wbudowane oprogramowanie pośredniczące
Platforma ASP.NET Core jest dostarczana z następującymi składnikami oprogramowania pośredniczącego. Kolumna Order zawiera uwagi na temat umieszczania oprogramowania pośredniczącego w potoku przetwarzania żądania oraz warunki, w których może ono przerwać przetwarzanie żądania. Gdy oprogramowanie pośredniczące przerywa potok przetwarzania żądania i uniemożliwia innemu oprogramowaniu pośredniczącemu dalsze przetwarzanie żądania, nazywane jest końcowym oprogramowaniem pośredniczącym. Aby uzyskać więcej informacji na temat zwarć, zobacz sekcję Tworzenie potoku oprogramowania pośredniczącego za pomocą aplikacji internetowej .
Konfiguruje współużytkowanie zasobów między źródłami.
Przed składnikami korzystającymi z mechanizmu CORS. Obecnie składnik UseCors musi znajdować się przed składnikiem UseResponseCaching z powodu tej usterki.
Generuje stronę z informacjami o błędzie przeznaczonymi do użytku tylko w środowisku programistycznym.
Przed składnikami, które generują błędy. Szablony projektów automatycznie rejestrują to oprogramowanie pośredniczące jako pierwszy komponent w potoku, gdy środowisko to Deweloperskie.
Kilka oddzielnych oprogramowań pośredniczących, które udostępniają stronę wyjątków dla deweloperów, obsługę wyjątków, strony kodu stanu i domyślną stronę internetową dla nowych aplikacji.
Przed składnikami, które generują błędy. Terminal obsługujący wyjątki lub domyślną stronę internetową dla nowych aplikacji.
Zapewnia obsługę buforowania odpowiedzi na podstawie konfiguracji.
Przed składnikami, które wymagają buforowania. Składnik UseRouting musi znajdować się przed składnikiem UseOutputCaching. Składnik UseCORS musi znajdować się przed składnikiem UseOutputCaching.
Zapewnia obsługę buforowania odpowiedzi. Wymaga to udziału klienta w pracy. Użyj buforowania danych wyjściowych do pełnej kontroli serwera.
Przed składnikami, które wymagają buforowania. Składnik UseCORS musi znajdować się przed składnikiem UseResponseCaching. Zazwyczaj nie jest korzystne dla aplikacji interfejsu użytkownika, takich jak Razor Strony, ponieważ przeglądarki zwykle ustawiają nagłówki żądań, które uniemożliwiają buforowanie.
Buforowanie danych wyjściowych zapewnia korzyści dla aplikacji interfejsu użytkownika.
Przed komponentami wrażliwymi na lokalizację. W przypadku korzystania ze składnika RouteDataRequestCultureProvider musi pojawiać się po oprogramowaniu pośredniczącym routingu.
Oprogramowanie pośredniczące to oprogramowanie, które jest wmontowane w potok aplikacji w celu obsługi żądań i odpowiedzi. Każdy składnik:
Wybiera, czy przekazać żądanie do następnego składnika w przepływie.
Może wykonywać pracę przed i po następnym składniku w potoku.
Delegaci żądań są używani do kompilowania potoku żądania. Delegaci żądań obsługują każde żądanie HTTP.
Delegaci żądań są konfigurowani przy użyciu metod rozszerzeń Run, Map i Use. Pojedynczego delegata żądania można określić wewnątrz kodu jako metodę anonimową (nazywaną środkiem wewnątrz kodu) lub zdefiniować w klasie wielokrotnego użytku. Te klasy wielokrotnego użytku i metody anonimowe w linii to oprogramowanie pośredniczące, nazywane również składnikami oprogramowania pośredniczącego. Każdy składnik oprogramowania pośredniczącego w potoku żądania jest odpowiedzialny za wywołanie następnego składnika w potoku lub przerwanie potoku. Gdy oprogramowanie pośredniczące przerywa działanie, jest ono nazywane końcowym oprogramowaniem pośredniczącym, ponieważ zapobiega dalszemu przetwarzaniu przez oprogramowanie pośredniczące.
Rola oprogramowania pośredniczącego według typu aplikacji
Razor Pages, MVC, Blazor Server, i przetwarzanie żądań przeglądarki przez projekt serwera hostowanego Blazor WebAssembly rozwiązania na serwerze z użyciem oprogramowania pośredniczącego. Wskazówki zawarte w tym artykule dotyczą tych typów aplikacji.
Autonomiczne aplikacje Blazor WebAssembly są uruchamiane w całości na kliencie i nie przetwarzają żądań przy użyciu kanału oprogramowania pośredniczącego. Wskazówki zawarte w tym artykule nie dotyczą autonomicznych aplikacji Blazor WebAssembly.
Analiza kodu oprogramowania pośredniczącego
Platforma ASP.NET Core zawiera wiele analizatorów platformy kompilatora, które sprawdzają kod aplikacji pod kątem jakości. Aby uzyskać więcej informacji, zobacz Analiza kodu w aplikacjach platformy ASP.NET Core
Utwórz przepływ middleware za pomocą elementu WebApplication
Potok żądań w platformie ASP.NET Core składa się z sekwencji delegatów żądań wywoływanych kolejno. Na poniższym diagramie przedstawiono tę koncepcję. Wątek wykonywania przebiega zgodnie z czarnymi strzałkami.
Każdy delegat może wykonywać operacje przed następnym delegatem i po nim. Delegaty obsługujące wyjątki powinny być wywoływane na wczesnym etapie w kolejce, aby mogły przechwytywać wyjątki występujące w późniejszych etapach kolejki.
Najprostsza możliwa aplikacja platformy ASP.NET Core konfiguruje jednego delegata żądania, który obsługuje wszystkie żądania. Ten przypadek nie obejmuje rzeczywistego procesu przetwarzania żądania. Zamiast tego w odpowiedzi na każde żądanie HTTP jest wywoływana jedna funkcja anonimowa.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Run(async context =>
{
await context.Response.WriteAsync("Hello world!");
});
app.Run();
Połącz wiele delegatów żądań razem za pomocą funkcji Use. Parametr next reprezentuje następnego delegata w linii przetwarzania. Można pominąć proces, gdy nie wywoła się parametr next. Zazwyczaj można wykonywać akcje zarówno przed delegatem next, jak i po nim, jak pokazano w poniższym przykładzie:
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();
Gdy delegat nie przekazuje żądania do następnego delegata, jest to nazywane tworzeniem skrótu w potoku żądania. Tworzenie skrótu jest często pożądane, ponieważ pozwala uniknąć niepotrzebnej pracy. Na przykład statyczne oprogramowanie pośredniczące plików może działać jako oprogramowanie pośredniczące terminalu, przetwarzając żądanie dotyczące pliku statycznego i zwarcie pozostałej części potoku. Oprogramowanie pośredniczące dodane do potoku przed oprogramowaniem pośredniczącym, które przerywa dalsze przetwarzanie, nadal przetwarza kod po instrukcjach next.Invoke. Zobacz jednak następujące ostrzeżenie dotyczące próby zapisania w odpowiedzi, która została już wysłana.
Ostrzeżenie
Nie wywołuj elementu next.Invoke po tym, jak odpowiedź została wysłana do klienta. Zmiany wprowadzone w składniku HttpResponse po rozpoczęciu odpowiedzi zgłaszają wyjątek. Na przykład ustawienie nagłówków i kodu stanu powoduje zgłoszenie wyjątku. Zapisywanie w treści odpowiedzi po wywołaniu składnika next:
Może spowodować naruszenie protokołu. Na przykład zapisanie dłuższej treści niż określona wartość Content-Length.
Może uszkodzić format ciała. Na przykład zapisanie stopki HTML do pliku CSS.
HasStarted to przydatna wskazówka informująca, czy nagłówki zostały wysłane lub czy treść została zapisana.
Delegaci Run nie otrzymują parametru next. Pierwszy delegat Run jest zawsze końcowy i zamyka potok.
Run to konwencja. Niektóre składniki oprogramowania pośredniczącego mogą uwidaczniać metody Run[Middleware] uruchamiane na końcu potoku:
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();
W poprzednim przykładzie delegat Run zapisuje "Hello from 2nd delegate." w odpowiedzi, a następnie przerywa potok. Jeśli inny delegat Use lub Run zostanie dodany po delegacie Run, nie będzie on wywoływany.
Preferuj przeciążenie metody app.Use, które wymaga przekazania kontekstu do następnego składnika.
Nieprzydzielająca metoda rozszerzenia funkcji app.Use:
Wymaga przekazania kontekstu do składnika next.
Oszczędza dwie wewnętrzne alokacje przy każdym żądaniu, które są wymagane podczas używania innego wariantu przeciążenia.
Aby uzyskać więcej informacji, zobacz ten problem w serwisie GitHub.
Kolejność oprogramowania pośredniczącego
Na poniższym diagramie przedstawiono kompletny potok przetwarzania żądania dla aplikacji MVC i Razor Pages na platformie ASP.NET Core. Można zobaczyć, jak w typowej aplikacji uporządkowane jest istniejące oprogramowanie pośredniczące i gdzie dodaje się niestandardowe oprogramowanie pośredniczące. Masz pełną kontrolę nad tym, jak zmienić kolejność istniejących oprogramowań pośredniczących lub wstrzyknąć nowe niestandardowe oprogramowania pośredniczące odpowiednio do potrzeb w scenariuszach.
Oprogramowanie pośredniczące punktu końcowego na powyższym diagramie wykonuje potok filtrów dla danego rodzaju aplikacji — MVC lub Razor Pages.
Na powyższym diagramie przedstawiony jest moduł pośredniczący Routing, który następuje po Pliki statyczne. Jest to kolejność implementowana w szablonach projektów przez jawne wywoływanie funkcji app.UseRouting. Jeśli nie wywołasz funkcji app.UseRouting, oprogramowanie pośredniczące Routing będzie domyślnie uruchamiane na początku potoku. Aby uzyskać więcej informacji, zobacz Routing.
Kolejność dodawania składników oprogramowania pośredniczącego w pliku Program.cs definiuje kolejność wywoływania składników oprogramowania pośredniczącego w żądaniach oraz odwrotną kolejność dla odpowiedzi. Kolejność ma kluczowe znaczenie dla bezpieczeństwa, wydajności i funkcjonalności.
Poniższy wyróżniony kod w programie Program.cs dodaje składniki oprogramowania pośredniczącego związane z zabezpieczeniami w typowej zalecanej kolejności:
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();
W poprzednim kodzie:
Oprogramowanie pośredniczące, które nie jest dodawane podczas tworzenia nowej aplikacji internetowej z kontami poszczególnych użytkowników, jest zakomentowane.
Nie każde oprogramowanie pośredniczące pojawia się w tej dokładnej kolejności, ale wiele tak. Na przykład:
UseCors, UseAuthentication i UseAuthorization muszą pojawić się w pokazanej kolejności.
UseRequestLocalization musi pojawić się przed wszelkim oprogramowaniem pośredniczącym, które może sprawdzać kulturę żądania, na przykład app.UseStaticFiles().
UseRateLimiter należy wywołać po UseRouting, gdy używane są interfejsy API specyficzne dla punktu końcowego ograniczające szybkość. Na przykład, jeśli używany jest atrybut [EnableRateLimiting], UseRateLimiter musi być wywołany po UseRouting. Podczas wywoływania tylko ograniczników globalnych UseRateLimiter można wywołać przed UseRouting.
W niektórych scenariuszach oprogramowanie pośredniczące ma inne określanie kolejności. Na przykład określanie kolejności buforowania i kompresji jest specyficzne dla scenariusza i istnieje wiele prawidłowych określeń kolejności. Na przykład:
W poprzednim kodzie użycie procesora CPU może zostać zmniejszone przez buforowanie skompresowanej odpowiedzi, ale może to doprowadzić do buforowania wielu reprezentacji zasobu przy użyciu różnych algorytmów kompresji, takich jak Gzip lub Brotli.
Poniższe określanie kolejności łączy pliki statyczne w celu umożliwienia buforowania skompresowanych plików statycznych:
Poniższy kod Program.cs dodaje składniki oprogramowania pośredniczącego dla typowych scenariuszy aplikacji:
Obsługa wyjątków/błędów
Gdy aplikacja jest uruchamiana w środowisku programistycznym:
Strona wyjątków programisty w middleware (UseDeveloperExceptionPage) zgłasza błędy w czasie działania aplikacji.
Oprogramowanie pośredniczące strony błędu bazy danych (UseDatabaseErrorPage) zgłasza błędy środowiska uruchomieniowego bazy danych.
Gdy aplikacja działa w środowisku produkcyjnym:
Oprogramowanie pośredniczące do obsługi wyjątków (UseExceptionHandler) przechwytuje wyjątki zgłoszone w kolejnych warstwach oprogramowania pośredniczącego.
Oprogramowanie pośredniczące do obsługi plików statycznych (UseStaticFiles) zwraca pliki statyczne i przerywa dalsze przetwarzanie żądania.
Oprogramowanie pośredniczące Cookie (UseCookiePolicy) zapewnia zgodność aplikacji z unijnym ogólnym rozporządzeniem o ochronie danych (RODO).
Oprogramowanie pośredniczące routingu (UseRouting) do kierowania żądań.
Oprogramowanie pośredniczące uwierzytelniania (UseAuthentication) próbuje uwierzytelnić użytkownika przed zezwoleniem mu na uzyskiwanie dostępu do bezpiecznych zasobów.
Oprogramowanie pośredniczące autoryzacji (UseAuthorization) autoryzuje użytkownika do uzyskiwania dostępu do bezpiecznych zasobów.
Oprogramowanie pośredniczące sesji (UseSession) ustanawia i utrzymuje stan sesji. Jeśli aplikacja używa stanu sesji, wywołaj oprogramowanie pośredniczące sesji po Policy Middleware Cookie i przed oprogramowaniem pośredniczącym MVC.
Oprogramowanie pośredniczące do routingu końcowego (UseEndpoints z MapRazorPages) służące do dodawania punktów końcowych Razor Pages do potoku żądania.
W poprzednim kodzie przykładowym każda metoda rozszerzenia oprogramowania pośredniczącego jest uwidoczniona w składniku WebApplicationBuilder za pośrednictwem przestrzeni nazw Microsoft.AspNetCore.Builder.
UseExceptionHandler to pierwszy komponent pośredniczący dodany do pipeline'u. Dlatego oprogramowanie pośredniczące programu obsługi wyjątków przechwytuje wszelkie wyjątki występujące w kolejnych wywołaniach.
Oprogramowanie pośredniczące do obsługi plików statycznych jest wywoływane na początku potoku, dzięki czemu może obsługiwać żądania i zakończyć przetwarzanie bez przechodzenia przez pozostałe składniki. Oprogramowanie pośredniczące plików statycznych nie wykonuje żadnych kontroli autoryzacji. Wszystkie pliki obsługiwane przez oprogramowanie pośredniczące plików statycznych, w tym te w katalogu wwwroot, są publicznie dostępne. Aby poznać metodę zabezpieczania plików statycznych, zobacz Pliki statyczne na platformie ASP.NET Core.
Jeśli żądanie nie jest obsługiwane przez oprogramowanie pośredniczące plików statycznych, jest przekazywane do oprogramowania pośredniczącego uwierzytelniania (UseAuthentication), które wykonuje uwierzytelnianie. Uwierzytelnianie nie pomija nieuwierzytelnionych żądań. Chociaż middleware uwierzytelniające uwierzytelnia żądania, autoryzacja (i odrzucenie) odbywa się dopiero po tym, jak MVC wybierze określoną stronę Razor lub kontroler MVC i akcję.
W poniższym przykładzie pokazano kolejność oprogramowania pośredniczącego, w której żądania dotyczące plików statycznych są obsługiwane przez oprogramowanie pośredniczące plików statycznych przed oprogramowaniem pośredniczącym kompresji odpowiedzi. Pliki statyczne nie są kompresowane w ramach tej kolejności oprogramowania pośredniczącego. Odpowiedzi Razor Pages można skompresować.
Aby uzyskać informacje o aplikacjach jednostronicowych, zobacz przewodniki dotyczące szablonów projektów React i Angular.
Kolejność elementów UseCors i UseStaticFiles
Kolejność wywoływania składników UseCors i UseStaticFiles zależy od aplikacji. Aby uzyskać więcej informacji, zobacz kolejność UseCors i UseStaticFiles
Kolejność obsługi przekazywanych nagłówków przez oprogramowanie pośredniczące
Oprogramowanie middleware przesyłanych nagłówków powinno być uruchamiane przed innym middleware. Takie określenie kolejności gwarantuje, że oprogramowanie pośredniczące, które opiera się na informacjach z przekazywanych nagłówków, może wykorzystywać wartości nagłówków do przetwarzania. Aby uruchomić oprogramowanie pośredniczące przekazanych nagłówków po oprogramowaniu pośredniczącym diagnostyki i obsługi błędów, zobacz Kolejność oprogramowania pośredniczącego przekazanych nagłówków.
Rozszerzenia Map są używane jako konwencja do rozgałęziania potoku. Składnik Map rozgałęzia potok żądania na podstawie dopasowań podanej ścieżki żądania. Jeśli ścieżka żądania rozpoczyna się od podanej ścieżki, wykonywane jest rozgałęzianie.
W poniższej tabeli przedstawiono żądania i odpowiedzi z adresu http://localhost:1234 przy użyciu poprzedzającego kodu.
Zażądaj
Odpowiedź
localhost:1234
Witam od delegata niebędącego częścią Map.
localhost:1234/map1
Map Test 1
localhost:1234/map2
Map Test 2
localhost:1234/map3
Cześć od delegata niebędącego częścią Map.
Gdy jest używany składnik Map, dopasowane segmenty ścieżki są usuwane ze składnika HttpRequest.Path i dołączane do składnika HttpRequest.PathBase dla każdego żądania.
Składnik Map może również jednocześnie pasować do wielu segmentów:
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");
});
}
Instrukcja MapWhen rozgałęzia potok żądania na podstawie wyniku danego predykatu. Dowolny predykat typu Func<HttpContext, bool> może zostać użyty do skierowania żądań na nową gałąź potoku. W poniższym przykładzie predykat jest używany do wykrywania obecności zmiennej ciągu zapytania 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}");
});
}
W poniższej tabeli przedstawiono żądania i odpowiedzi z adresu http://localhost:1234 przy użyciu poprzedniego kodu:
Zażądaj
Odpowiedź
localhost:1234
Hello from non-Map delegate.
localhost:1234/?branch=main
Branch used = main
Instrukcja UseWhen rozgałęzia także potok żądania na podstawie wyniku danego predykatu. W przeciwieństwie do MapWhen, ta gałąź jest ponownie dołączana do głównego potoku, jeśli nie przerywa działania ani nie zawiera końcowego oprogramowania pośredniczącego.
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.
});
}
W poprzednim przykładzie dla wszystkich żądań jest pisana odpowiedź Hello from non-Map delegate.. Jeśli żądanie zawiera zmienną ciągu zapytania branch, jego wartość jest rejestrowana przed ponownym włączeniem do głównego przepływu.
Wbudowane oprogramowanie pośredniczące
Platforma ASP.NET Core jest dostarczana z następującymi składnikami oprogramowania pośredniczącego. Kolumna Order zawiera uwagi na temat umieszczania oprogramowania pośredniczącego w potoku przetwarzania żądań oraz warunki, w których może ono zakończyć przetwarzanie żądania. Gdy oprogramowanie pośredniczące przerywa potok przetwarzania żądania i uniemożliwia dalsze przetwarzanie żądania przez inne oprogramowanie pośredniczące, nazywane jest końcowym oprogramowaniem pośredniczącym. Aby uzyskać więcej informacji na temat zwarć, zobacz sekcję Tworzenie potoku oprogramowania pośredniczącego za pomocą aplikacji internetowej .
Konfiguruje współużytkowanie zasobów między źródłami.
Przed składnikami korzystającymi z mechanizmu CORS. Obecnie składnik UseCors musi znajdować się przed składnikiem UseResponseCaching z powodu tej usterki.
Generuje stronę z informacjami o błędzie przeznaczonymi do użytku tylko w środowisku programistycznym.
Przed składnikami, które generują błędy. Szablony projektów automatycznie rejestrują to oprogramowanie pośredniczące jako pierwsze w potoku, gdy środowisko jest ustawione na deweloperskie.
Kilka oddzielnych oprogramowań pośredniczących, które udostępniają stronę wyjątków dla deweloperów, obsługę wyjątków, strony kodu stanu i domyślną stronę internetową dla nowych aplikacji.
Przed składnikami, które generują błędy. Terminal obsługujący wyjątki lub serwujący domyślną stronę internetową dla nowych aplikacji.
Zapewnia obsługę buforowania odpowiedzi na podstawie konfiguracji.
Przed składnikami, które wymagają buforowania. Składnik UseRouting musi znajdować się przed składnikiem UseOutputCaching. Składnik UseCORS musi znajdować się przed składnikiem UseOutputCaching.
Zapewnia wsparcie dla buforowania odpowiedzi. Wymaga to udziału klienta w pracy. Użyj buforowania danych wyjściowych do pełnej kontroli serwera.
Przed składnikami wymagającymi buforowania. Składnik UseCORS musi znajdować się przed składnikiem UseResponseCaching. Zazwyczaj nie jest korzystne dla aplikacji interfejsu użytkownika, takich jak Razor Strony, ponieważ przeglądarki zwykle ustawiają nagłówki żądań, które uniemożliwiają buforowanie.
Buforowanie danych wyjściowych zapewnia korzyści dla aplikacji interfejsu użytkownika.
Przed składnikami czułymi na lokalizację. W przypadku korzystania ze składnika RouteDataRequestCultureProvider musi pojawiać się po oprogramowaniu pośredniczącym routingu.
Oprogramowanie pośredniczące to oprogramowanie, które jest wmontowane w potok aplikacji w celu obsługi żądań i odpowiedzi. Każdy składnik:
Określa, czy należy przekazać żądanie do następnego składnika w potoku.
Może wykonywać pracę przed i po następnym elemencie w przepływie pracy.
Delegaci żądań są używani do kompilowania potoku żądania. Delegaci żądań obsługują każde żądanie HTTP.
Delegaci żądań są konfigurowani przy użyciu metod rozszerzeń Run, Map i Use. Pojedynczego delegata żądania można określić bezpośrednio w kodzie jako metodę anonimową (nazywaną middleware in-line) lub można go zdefiniować w klasie wielokrotnego użytku. Te klasy do ponownego użycia i osadzone w kodzie metody anonimowe to middleware, nazywane również składnikami middleware. Każdy komponent oprogramowania pośredniczącego w potoku żądania jest odpowiedzialny za wywołanie następnego komponentu w potoku lub przerwanie działania potoku. Gdy oprogramowanie pośredniczące przerywa działanie, jest ono nazywane końcowym oprogramowaniem pośredniczącym, ponieważ zapobiega przetwarzaniu żądania przez dalsze oprogramowanie pośredniczące.
Platforma ASP.NET Core zawiera wiele analizatorów platformy kompilatora, które sprawdzają kod aplikacji pod kątem jakości. Aby uzyskać więcej informacji, zobacz Analiza kodu w aplikacjach platformy ASP.NET Core
Utwórz potok oprogramowania pośredniczącego z WebApplication
Potok przetwarzania żądań w ASP.NET Core składa się z sekwencji delegatów żądań wywoływanych kolejno. Na poniższym diagramie przedstawiono tę koncepcję. Wykonywanie wątku przebiega zgodnie z czarnymi strzałkami.
Każdy delegat może wykonywać operacje przed następnym delegatem i po nim. Delegaty obsługujące wyjątki powinny być wywoływane na wczesnym etapie ciągu procesów, aby mogły przechwytywać wyjątki występujące w późniejszych etapach tego ciągu.
Najprostsza możliwa aplikacja platformy ASP.NET Core konfiguruje jednego delegata żądania, który obsługuje wszystkie żądania. W tym przypadku nie obejmuje rzeczywistego kanału przetwarzania żądań. Zamiast tego w odpowiedzi na każde żądanie HTTP jest wywoływana jedna funkcja anonimowa.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Run(async context =>
{
await context.Response.WriteAsync("Hello world!");
});
app.Run();
Połącz wiele delegatów żądań razem za pomocą funkcji Use. Parametr next reprezentuje następnego delegata w potoku. Można skrócić działanie potoku, gdy nie wywołuje się parametr next. Zazwyczaj można wykonywać akcje zarówno przed delegatem next, jak i po nim, jak pokazano w poniższym przykładzie:
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();
Gdy delegat nie przekazuje żądania do następnego delegata, jest to nazywane przerywaniem potoku żądań. Tworzenie skrótu jest często pożądane, ponieważ pozwala uniknąć niepotrzebnej pracy. Na przykład statyczne oprogramowanie pośredniczące plików może działać jako oprogramowanie pośredniczące terminalu, przetwarzając żądanie dotyczące pliku statycznego i zwarcie pozostałej części potoku. Oprogramowanie pośredniczące dodane do potoku przed oprogramowaniem pośredniczącym, które przerywa dalsze przetwarzanie, nadal przetwarza kod po instrukcjach next.Invoke. Jednak zwróć uwagę na poniższe ostrzeżenie dotyczące próby zapisania w odpowiedzi, która została już wysłana.
Ostrzeżenie
Nie wywołuj next.Invoke po wysłaniu odpowiedzi do klienta. Zmiany w HttpResponse po rozpoczęciu wysyłania odpowiedzi zgłaszają wyjątek. Na przykład ustawienie nagłówków i kodu stanu zgłasza wyjątek. Zapisywanie w treści odpowiedzi po wywołaniu składnika next:
Może spowodować naruszenie protokołu. Na przykład zapisanie dłuższej treści niż określona wartość Content-Length.
Może uszkodzić format ciała. Na przykład zapisanie stopki HTML w pliku CSS.
HasStarted to przydatna wskazówka informująca, czy nagłówki zostały wysłane lub czy treść została zapisana.
Delegaci Run nie otrzymują parametru next. Pierwszy delegat Run jest zawsze końcowym delegatem i zakończa potok.
Run to konwencja. Niektóre składniki oprogramowania pośredniczącego mogą uwidaczniać metody Run[Middleware] uruchamiane na końcu potoku:
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();
W poprzednim przykładzie delegat Run zapisuje "Hello from 2nd delegate." w odpowiedzi, a następnie przerywa potok. Jeśli inny delegat Use lub Run zostanie dodany po delegacie Run, nie będzie on wywoływany.
Preferuj przeciążenie metody app.Use, które wymaga przekazania kontekstu do następnego składnika.
Zapisuje dwie wewnętrzne alokacje na żądanie, które są wymagane podczas używania innego przeciążenia.
Aby uzyskać więcej informacji, zobacz ten problem w serwisie GitHub.
Kolejność oprogramowania pośredniczącego
Na poniższym diagramie przedstawiono kompletny potok przetwarzania żądania dla aplikacji MVC i Razor Pages na platformie ASP.NET Core. Można zobaczyć, jak w typowej aplikacji są uporządkowane istniejące middlewary i gdzie dodawane są niestandardowe middlewary. Masz pełną kontrolę nad tym, jak zmienić kolejność istniejących oprogramowań pośredniczących lub wstrzyknąć nowe niestandardowe oprogramowania pośredniczące odpowiednio do potrzeb w scenariuszach.
Oprogramowanie pośredniczące Endpoint na powyższym diagramie wykonuje potok filtru dla odpowiedniego typu aplikacji — MVC lub Razor Strony.
Na powyższym diagramie jest przedstawione oprogramowanie pośredniczące Routing, które następuje po oprogramowaniu Pliki statyczne. Jest to kolejność implementowana w szablonach projektów przez jawne wywoływanie funkcji app.UseRouting. Jeśli nie wywołasz funkcji app.UseRouting, oprogramowanie pośredniczące Routing będzie domyślnie uruchamiane na początku potoku. Aby uzyskać więcej informacji, zobacz Routing.
Kolejność dodawania składników oprogramowania pośredniczącego w pliku Program.cs definiuje kolejność wywoływania składników oprogramowania pośredniczącego w żądaniach oraz odwrotną kolejność dla odpowiedzi. Kolejność ma kluczowe znaczenie dla bezpieczeństwa, wydajności i funkcjonalności.
Poniższy wyróżniony kod w programie Program.cs dodaje składniki oprogramowania pośredniczącego związane z zabezpieczeniami w typowej zalecanej kolejności:
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();
W poprzednim fragmencie kodu:
Oprogramowanie pośredniczące, które nie jest dodawane podczas tworzenia nowej aplikacji internetowej z kontami poszczególnych użytkowników, jest zakomentowane.
Nie każde oprogramowanie pośredniczące pojawia się w tej dokładnej kolejności, ale wiele tak. Na przykład:
UseCors, UseAuthentication i UseAuthorization muszą pojawić się w podanej kolejności.
Element UseRequestLocalization musi pojawić się przed jakimkolwiek middleware, które może sprawdzić kulturę żądania (na przykład app.UseMvcWithDefaultRoute()).
W niektórych scenariuszach oprogramowanie pośredniczące ma inne określanie kolejności. Na przykład określanie kolejności buforowania i kompresji jest specyficzne dla scenariusza i istnieje wiele prawidłowych określeń kolejności. Na przykład:
W poprzednim kodzie użycie procesora CPU może zostać zmniejszone przez buforowanie skompresowanej odpowiedzi, ale może to doprowadzić do buforowania wielu reprezentacji zasobu przy użyciu różnych algorytmów kompresji, takich jak Gzip lub Brotli.
Poniższe określanie kolejności łączy pliki statyczne w celu umożliwienia buforowania skompresowanych plików statycznych:
Oprogramowanie pośredniczące plików statycznych (UseStaticFiles) zwraca pliki statyczne i pomija dalsze przetwarzanie żądania.
Oprogramowanie pośredniczące Cookie (UseCookiePolicy) zapewnia zgodność aplikacji z ogólnym rozporządzeniem o ochronie danych (RODO) UE.
Oprogramowanie pośredniczące (UseRouting) do trasowania żądań.
Oprogramowanie pośredniczące uwierzytelniania (UseAuthentication) próbuje uwierzytelnić użytkownika przed zezwoleniem mu na uzyskiwanie dostępu do bezpiecznych zasobów.
Oprogramowanie pośredniczące autoryzacji (UseAuthorization) autoryzuje użytkownika do uzyskiwania dostępu do bezpiecznych zasobów.
Oprogramowanie pośredniczące sesji (UseSession) ustanawia i utrzymuje stan sesji. Jeśli aplikacja używa stanu sesji, wywołaj oprogramowanie pośredniczące sesji po oprogramowaniu pośredniczącym zasad dotyczących plików Cookie i przed oprogramowaniem pośredniczącym MVC.
Pośredniczące oprogramowanie routingu punktu końcowego (UseEndpoints z MapRazorPages) służące do dodawania punktów końcowych stron Razor do potoku żądania.
W poprzednim kodzie przykładowym każda metoda rozszerzenia oprogramowania pośredniczącego jest uwidoczniona w składniku WebApplicationBuilder za pośrednictwem przestrzeni nazw Microsoft.AspNetCore.Builder.
UseExceptionHandler to pierwszy składnik oprogramowania pośredniczącego dodany do potoku. Dlatego Middleware obsługujący wyjątki przechwytuje wszelkie wyjątki występujące w dalszych wywołaniach.
Oprogramowanie middleware do obsługi plików statycznych jest wywoływane na początku potoku, dzięki czemu może obsługiwać żądania i pominąć pozostałe składniki. Oprogramowanie pośredniczące plików statycznych nie przeprowadza kontroli autoryzacji. Wszystkie pliki obsługiwane przez oprogramowanie pośredniczące plików statycznych, w tym te w katalogu wwwroot, są publicznie dostępne. Aby poznać metodę zabezpieczania plików statycznych, zobacz Pliki statyczne na platformie ASP.NET Core.
Jeśli żądanie nie jest obsługiwane przez oprogramowanie pośredniczące plików statycznych, jest przekazywane do oprogramowania pośredniczącego uwierzytelniania (UseAuthentication), które wykonuje uwierzytelnianie. Uwierzytelnianie nie pomija nieuwierzytelnionych żądań. Mimo że oprogramowanie pośredniczące uwierzytelniania uwierzytelnia żądania, autoryzacja (i odrzucenie) występuje dopiero po tym, jak MVC wybiera konkretną stronę Razor lub kontroler MVC i akcję.
W poniższym przykładzie pokazano kolejność oprogramowania pośredniczącego, w której żądania dotyczące plików statycznych są obsługiwane przez oprogramowanie pośredniczące plików statycznych przed oprogramowaniem pośredniczącym kompresji odpowiedzi. Pliki statyczne nie są kompresowane w ramach tej kolejności oprogramowania pośredniczącego. Można skompresować odpowiedzi Pages.
Oprogramowanie pośredniczące do przekazywania nagłówków powinno działać przed innym oprogramowaniem pośredniczącym. Takie określenie kolejności gwarantuje, że middleware polegające na informacjach z przekazywanych nagłówków może używać wartości nagłówków do przetwarzania. Aby uruchomić oprogramowanie pośredniczące przekazanych nagłówków po oprogramowaniu pośredniczącym diagnostyki i obsługi błędów, zobacz Kolejność oprogramowania pośredniczącego przekazanych nagłówków.
Rozszerzenia Map są używane jako standard do rozgałęziania przepływu. Element Map rozgałęzia przepływ żądania na podstawie dopasowań podanej ścieżki żądania. Jeśli ścieżka żądania rozpoczyna się od podanej ścieżki, wykonywane jest rozgałęzianie.
W poniższej tabeli przedstawiono żądania i odpowiedzi z adresu http://localhost:1234 przy użyciu poprzedzającego kodu.
Zażądaj
Odpowiedź
localhost:1234
Witaj od delegata niezwiązanego z Mapą.
localhost:1234/map1
Mapa Test 1
localhost:1234/map2
Map Test 2
localhost:1234/map3
Witam od delegata spoza mapy.
Gdy jest używany składnik Map, dopasowane segmenty ścieżki są usuwane ze składnika HttpRequest.Path i dołączane do składnika HttpRequest.PathBase dla każdego żądania.
Składnik Map może również jednocześnie pasować do wielu segmentów:
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");
});
}
Instrukcja MapWhen rozgałęzia potok żądania na podstawie wyniku danego predykatu. Dowolny predykat typu Func<HttpContext, bool> może zostać użyty do mapowania żądań na nową gałąź przepływu. W poniższym przykładzie predykat jest używany do wykrywania obecności zmiennej ciągu zapytania 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}");
});
}
W poniższej tabeli przedstawiono żądania i odpowiedzi z adresu http://localhost:1234 przy użyciu poprzedniego kodu:
Zażądaj
Odpowiedź
localhost:1234
Hello from non-Map delegate.
localhost:1234/?branch=main
Branch used = main
Instrukcja UseWhen rozgałęzia także potok żądania na podstawie wyniku danego predykatu. W odróżnieniu od MapWhen, ta gałąź jest ponownie dołączana do głównej ścieżki, jeśli nie dochodzi do krótkiego spięcia lub nie zawiera terminalnego 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.
});
}
W poprzednim przykładzie dla wszystkich żądań jest pisana odpowiedź Hello from non-Map delegate.. Jeśli żądanie zawiera zmienną ciągu zapytania branch, jego wartość jest rejestrowana przed ponownym dołączeniem do potoku głównego.
Wbudowane oprogramowanie pośredniczące
Platforma ASP.NET Core jest dostarczana z następującymi składnikami oprogramowania pośredniczącego. Kolumna Order zawiera informacje dotyczące rozmieszczenia oprogramowania pośredniczącego w potoku przetwarzania żądania oraz warunków, w których oprogramowanie pośredniczące może przerwać przetwarzanie żądania. Gdy oprogramowanie pośredniczące przerywa potok przetwarzania żądania i uniemożliwia dalszym komponentom pośredniczącym przetwarzanie żądania, jest nazywane końcowym oprogramowaniem pośredniczącym. Aby uzyskać więcej informacji na temat zwarć, zobacz sekcję Tworzenie potoku oprogramowania pośredniczącego za pomocą aplikacji internetowej .
Konfiguruje współużytkowanie zasobów między źródłami.
Przed składnikami korzystającymi z mechanizmu CORS. Obecnie składnik UseCors musi znajdować się przed składnikiem UseResponseCaching z powodu tej usterki.
Generuje stronę z informacjami o błędzie przeznaczonymi do użytku tylko w środowisku programistycznym.
Przed składnikami, które generują błędy. Szablony projektów automatycznie rejestrują to oprogramowanie pośredniczące jako pierwsze w potoku, gdy środowisko to Rozwój.
Kilka oddzielnych oprogramowań pośredniczących, które udostępniają stronę wyjątków dla deweloperów, obsługę wyjątków, strony kodu stanu i domyślną stronę internetową dla nowych aplikacji.
Przed składnikami, które generują błędy. Terminal dla wyjątków lub obsługi domyślnej strony internetowej dla nowych aplikacji.
Przed komponentami wrażliwymi na lokalizację. Korzystając ze składnika RouteDataRequestCultureProvider, należy umieścić go za oprogramowaniem pośredniczącym routingu.
Przed składnikami wymaganymi do obsługi żądań WebSocket.
Dodatkowe zasoby
Opcje cyklu życia i rejestracji zawierają kompletny przykład oprogramowania pośredniczącego z usługami o cyklu życia o określonym zakresie, przejściowym i singleton.
Oprogramowanie pośredniczące to oprogramowanie, które jest wmontowane w potok aplikacji w celu obsługi żądań i odpowiedzi. Każdy składnik:
Określa, czy przekazać żądanie do następnego składnika w potoku.
Może wykonywać pracę przed i po następnym komponencie w łańcuchu zadań.
Delegaci żądań są używani do kompilowania potoku żądania. Delegaci żądań obsługują każde żądanie HTTP.
Delegaci żądań są konfigurowani przy użyciu metod rozszerzeń Run, Map i Use. Delegata dla pojedynczego żądania można określić w linii jako metodę anonimową (nazywaną w linii oprogramowaniem pośredniczącym) lub zdefiniować w odrębnej klasie. Te klasy wielokrotnego użytku i wbudowane metody anonimowe to middleware, nazywane również składnikami middleware. Każdy składnik oprogramowania pośredniczącego w potoku żądania jest odpowiedzialny za wywoływanie następnego składnika w potoku lub tworzenie skrótu w potoku. Gdy oprogramowanie pośredniczące zatrzymuje się, jest ono nazywane końcowym oprogramowaniem pośredniczącym, ponieważ zapobiega przetwarzaniu żądania przez dalsze oprogramowanie pośredniczące.
Tworzenie potoku oprogramowania pośredniczącego przy użyciu programu IApplicationBuilder
Potok przetwarzania żądań platformy ASP.NET Core składa się z sekwencji delegatów, które są wywoływane jeden po drugim. Na poniższym diagramie przedstawiono tę koncepcję. Wykonywanie wątku przebiega zgodnie z czarnymi strzałkami.
Każdy delegat może wykonywać operacje przed następnym delegatem i po nim. Delegaci obsługujący wyjątki powinni być wywoływani na wczesnym etapie w potoku, aby mogli przechwytywać wyjątki występujące w późniejszych etapach potoku.
Najprostsza możliwa aplikacja platformy ASP.NET Core konfiguruje jednego delegata żądania, który obsługuje wszystkie żądania. Ten scenariusz nie obejmuje rzeczywistego przepływu żądania. Zamiast tego w odpowiedzi na każde żądanie HTTP jest wywoływana jedna funkcja anonimowa.
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Hello, World!");
});
}
}
Połącz wiele delegatów żądań razem za pomocą funkcji Use. Parametr next reprezentuje kolejnego delegata w potoku. Można przerwać przepływ danych, nie wywołując parametru next. Zazwyczaj można wykonywać akcje zarówno przed następnym delegatem, jak i po nim, jak pokazano w poniższym przykładzie:
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.");
});
}
}
Gdy delegat nie przekazuje żądania do następnego delegata, jest to nazywane tworzeniem skrótu w potoku żądania. Krótkie spięcie jest często pożądane, ponieważ pozwala uniknąć niepotrzebnej pracy. Na przykład statyczne oprogramowanie pośredniczące plików może działać jako oprogramowanie pośredniczące terminalu, przetwarzając żądanie dotyczące pliku statycznego i zwarcie pozostałej części potoku. Oprogramowanie pośredniczące dodane do potoku przed oprogramowaniem pośredniczącym, które przerywa dalsze przetwarzanie, nadal przetwarza kod po instrukcjach next.Invoke. Należy mieć na uwadze następujące ostrzeżenie dotyczące próby zapisania odpowiedzi, która została już wysłana.
Może spowodować naruszenie protokołu. Na przykład zapisanie dłuższej treści niż określona wartość Content-Length.
Może uszkodzić format ciała. Na przykład zapisanie stopki HTML w pliku CSS.
HasStarted to przydatna wskazówka informująca, czy nagłówki zostały wysłane lub czy zapisano w treści.
Delegaci Run nie otrzymują parametru next. Pierwszy delegat Run jest zawsze końcowym i przerywa potok.
Run to konwencja. Niektóre składniki oprogramowania pośredniczącego mogą udostępniać metody Run[Middleware] uruchamiane na końcu przepływu danych.
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.");
});
}
}
W poprzednim przykładzie delegat Run zapisuje "Hello from 2nd delegate." w odpowiedzi, a następnie przerywa przepływ danych. Jeśli inny delegat Use lub Run zostanie dodany po delegacie Run, nie będzie on wywoływany.
Kolejność oprogramowania pośredniczącego
Na poniższym diagramie przedstawiono kompletny potok przetwarzania żądania dla aplikacji MVC i Razor Pages na platformie ASP.NET Core. Można zobaczyć, jak uporządkowane są istniejące middleware w typowej aplikacji i gdzie są dodawane niestandardowe middleware. Masz pełną kontrolę nad tym, jak zmienić kolejność istniejących oprogramowań pośredniczących lub wstrzyknąć nowe niestandardowe oprogramowania pośredniczące odpowiednio do potrzeb w scenariuszach.
Oprogramowanie pośredniczące punktu końcowego na powyższym diagramie wykonuje potok filtru dla odpowiedniego typu aplikacji — MVC lub Razor Pages.
Kolejność dodawania składników oprogramowania pośredniczącego w metodzie Startup.Configure definiuje kolejność wywoływania składników oprogramowania pośredniczącego w żądaniach oraz odwrotną kolejność dla odpowiedzi. Kolejność ma kluczowe znaczenie dla bezpieczeństwa, wydajności i funkcjonalności.
Poniższa metoda Startup.Configure dodaje składniki oprogramowania pośredniczącego związane z zabezpieczeniami w typowej zalecanej kolejności:
Oprogramowanie pośredniczące, które nie zostaje dodane podczas tworzenia nowej aplikacji internetowej z kontami indywidualnych użytkowników, jest zakomentowane.
Nie każde oprogramowanie pośredniczące pojawia się w tej dokładnej kolejności, ale wiele tak. Na przykład:
Elementy UseCors, UseAuthentication i UseAuthorization powinny pojawić się w pokazanej kolejności.
Obecnie składnik UseCors musi pojawiać się przed składnikiem UseResponseCaching z powodu tej usterki.
Metoda UseRequestLocalization musi pojawić się przed jakimkolwiek oprogramowaniem pośredniczącym, które może sprawdzić kulturę żądania (na przykład app.UseMvcWithDefaultRoute()).
W niektórych scenariuszach oprogramowanie pośredniczące ma inne określanie kolejności. Na przykład określanie kolejności buforowania i kompresji jest specyficzne dla scenariusza i istnieje wiele prawidłowych określeń kolejności. Na przykład:
W poprzednim kodzie można oszczędzać zasoby procesora CPU przez buforowanie skompresowanej odpowiedzi, ale może to doprowadzić do buforowania wielu reprezentacji zasobu przy użyciu różnych algorytmów kompresji, takich jak Gzip lub Brotli.
Poniższe określanie kolejności łączy pliki statyczne w celu umożliwienia buforowania skompresowanych plików statycznych:
Oprogramowanie pośredniczące plików statycznych (UseStaticFiles) zwraca pliki statyczne i omija dalsze przetwarzanie żądania.
Oprogramowanie pośredniczące Cookie (UseCookiePolicy) dostosowuje aplikację do przepisów ogólnego rozporządzenia o ochronie danych osobowych (RODO) w UE.
Oprogramowanie pośredniczące routingu (UseRouting) do kierowania żądań.
Oprogramowanie pośredniczące uwierzytelniania (UseAuthentication) próbuje uwierzytelnić użytkownika przed zezwoleniem mu na uzyskiwanie dostępu do bezpiecznych zasobów.
Oprogramowanie pośredniczące autoryzacji (UseAuthorization) autoryzuje użytkownika do uzyskiwania dostępu do bezpiecznych zasobów.
Oprogramowanie pośredniczące sesji (UseSession) ustanawia i utrzymuje stan sesji. Jeśli aplikacja używa stanu sesji, wywołaj oprogramowanie pośredniczące sesji po oprogramowaniu pośredniczącym dotyczącym zasad Cookie i przed oprogramowaniem pośredniczącym MVC.
Oprogramowanie pośredniczące routingu punktu końcowego (UseEndpoints z MapRazorPages) służące do dodawania punktów końcowych stron Razor do potoku żądania.
W poprzednim kodzie przykładowym każda metoda rozszerzenia oprogramowania pośredniczącego jest uwidoczniona w składniku IApplicationBuilder za pośrednictwem przestrzeni nazw Microsoft.AspNetCore.Builder.
UseExceptionHandler to pierwszy komponent oprogramowania pośredniczącego dodany do potoku. Dlatego middleware obsługujący wyjątki przechwytuje wszelkie wyjątki występujące w kolejnych wywołaniach.
Oprogramowanie pośredniczące plików statycznych jest wywoływane na początku potoku, dzięki czemu może obsługiwać żądania i tworzyć skrót bez przechodzenia przez pozostałe składniki. Oprogramowanie pośredniczące plików statycznych nie wykonuje kontroli autoryzacji. Wszystkie pliki obsługiwane przez oprogramowanie pośredniczące plików statycznych, w tym te w katalogu wwwroot, są publicznie dostępne. Aby poznać metodę zabezpieczania plików statycznych, zobacz Pliki statyczne na platformie ASP.NET Core.
Jeśli żądanie nie jest obsługiwane przez oprogramowanie pośredniczące plików statycznych, jest przekazywane do oprogramowania pośredniczącego uwierzytelniania (UseAuthentication), które wykonuje uwierzytelnianie. Uwierzytelnianie nie omija ani nie przerywa obsługi nieuwierzytelnionych żądań. Mimo że oprogramowanie pośredniczące uwierzytelniania uwierzytelnia żądania, autoryzacja (i odrzucenie) następuje dopiero po wybraniu przez MVC określonej strony Razor lub kontrolera i akcji MVC.
W poniższym przykładzie pokazano kolejność oprogramowania pośredniczącego, w której żądania dotyczące plików statycznych są obsługiwane przez oprogramowanie pośredniczące plików statycznych przed oprogramowaniem pośredniczącym kompresji odpowiedzi. Pliki statyczne nie są kompresowane w ramach tej kolejności oprogramowania pośredniczącego. Odpowiedzi Razor Pages można skompresować.
W przypadku aplikacji jednostronicowych (SPA) oprogramowanie pośredniczące aplikacji SPA UseSpaStaticFiles zwykle jest ostatnie w potoku oprogramowania pośredniczącego. Oprogramowanie pośredniczące aplikacji SPA pojawia się na końcu.
Aby umożliwić wszystkim innym oprogramowaniom pośredniczącym najpierw reagowanie na pasujące żądania.
Aby umożliwić uruchamianie aplikacji SPA z routingiem po stronie klienta dla wszystkich tras, które są nierozpoznane przez aplikację serwerową.
Aby uzyskać więcej szczegółowych informacji dotyczących aplikacji SPA, zobacz przewodniki dotyczące szablonów projektów React i Angular.
Kolejność przekazywanych nagłówków w oprogramowaniu pośredniczącym
Oprogramowanie pośredniczące dla przekazanych nagłówków powinno działać przed innymi komponentami pośredniczącymi. Takie ustawienie kolejności gwarantuje, że oprogramowanie pośredniczące korzystające z informacji z przekazanych nagłówków może wykorzystywać wartości nagłówków do przetwarzania. Aby uruchomić oprogramowanie pośredniczące przekazanych nagłówków po oprogramowaniu pośredniczącym diagnostyki i obsługi błędów, zobacz Kolejność oprogramowania pośredniczącego przekazanych nagłówków.
Rozszerzenia Map są używane jako konwencja do rozgałęziania potoku. Komponent Map rozgałęzia potok żądań na podstawie dopasowania podanej ścieżki żądania. Jeśli ścieżka żądania rozpoczyna się od podanej ścieżki, wykonywane jest rozgałęzianie.
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.");
});
}
}
W poniższej tabeli przedstawiono żądania i odpowiedzi z adresu http://localhost:1234 przy użyciu poprzedniego kodu.
Zażądaj
Odpowiedź
localhost:1234
Witam od delegata spoza mapy.
localhost:1234/map1
Test mapy 1
localhost:1234/map2
Map Test 2
localhost:1234/map3
Witaj od delegata spoza Mapy.
Gdy jest używany składnik Map, dopasowane segmenty ścieżki są usuwane ze składnika HttpRequest.Path i dołączane do składnika HttpRequest.PathBase dla każdego żądania.
Składnik Map obsługuje zagnieżdżanie, na przykład:
Składnik Map może również jednocześnie pasować do wielu segmentów:
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.");
});
}
}
Instrukcja MapWhen rozgałęzia potok żądania na podstawie wyniku danego predykatu. Dowolny predykat typu Func<HttpContext, bool> może zostać użyty do mapowania żądań na nową gałąź potoku. W poniższym przykładzie predykat jest używany do wykrywania obecności zmiennej ciągu zapytania 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.");
});
}
}
W poniższej tabeli przedstawiono żądania i odpowiedzi z adresu http://localhost:1234 przy użyciu poprzedniego kodu:
Zażądaj
Odpowiedź
localhost:1234
Witaj od delegata niepowiązanego z Mapą.
localhost:1234/?branch=main
Używana gałąź = main
Instrukcja UseWhen rozgałęzia także potok żądania na podstawie wyniku danego predykatu. Inaczej niż w przypadku MapWhen, ta gałąź jest ponownie dołączana do głównego potoku, jeśli nie przerywa ani nie zawiera końcowego 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.");
});
}
}
W poprzednim przykładzie dla wszystkich żądań jest pisana odpowiedź „Hello from main pipeline” (Pozdrowienia od głównego potoku). Jeśli żądanie zawiera zmienną ciągu zapytania branch, jej wartość zostaje zarejestrowana przed ponownym włączeniem do głównego przepływu przetwarzania.
Wbudowane oprogramowanie pośredniczące
Platforma ASP.NET Core jest dostarczana z następującymi składnikami oprogramowania pośredniczącego. Kolumna Order (Kolejność) zawiera uwagi dotyczące umieszczania pośrednictwa w potoku przetwarzania żądań oraz warunki, w jakich pośrednictwo może zakończyć przetwarzanie żądania. Gdy oprogramowanie pośredniczące przerywa proces przetwarzania żądania i uniemożliwia kolejnym warstwom oprogramowania pośredniczącego przetwarzanie żądania, jest nazywane terminalnym oprogramowaniem pośredniczącym. Aby uzyskać więcej informacji na temat tworzenia skrótów, zobacz sekcję Tworzenie potoku oprogramowania pośredniczącego przy użyciu programu IApplicationBuilder.
Konfiguruje współużytkowanie zasobów między źródłami.
Przed składnikami korzystającymi z mechanizmu CORS. Obecnie składnik UseCors musi znajdować się przed składnikiem UseResponseCaching z powodu tej usterki.
Kilka oddzielnych oprogramowań pośredniczących, które udostępniają stronę wyjątków dla deweloperów, obsługę wyjątków, strony kodu stanu i domyślną stronę internetową dla nowych aplikacji.
Przed składnikami, które generują błędy. Terminal do wyjątków lub do obsługi domyślnej strony internetowej dla nowych aplikacji.
Przed komponentami wrażliwymi na lokalizację. Korzystając ze składnika RouteDataRequestCultureProvider, musi pojawiać się po oprogramowaniu pośredniczącym do routingu.
Źródło tej zawartości można znaleźć w witrynie GitHub, gdzie można również tworzyć i przeglądać problemy i żądania ściągnięcia. Więcej informacji znajdziesz w naszym przewodniku dla współtwórców.
Opinia o produkcie ASP.NET Core
ASP.NET Core to projekt typu open source. Wybierz link, aby przekazać opinię:
Omówienie i implementowanie oprogramowania pośredniczącego w aplikacji ASP.NET Core. Użyj dołączonego oprogramowania pośredniczącego, takiego jak rejestrowanie HTTP i uwierzytelnianie. Utwórz niestandardowe oprogramowanie pośredniczące do obsługi żądań i odpowiedzi.