diff --git a/aspnetcore/blazor/host-and-deploy/app-base-path.md b/aspnetcore/blazor/host-and-deploy/app-base-path.md index 440b9c4557e7..5117cebc7e3a 100644 --- a/aspnetcore/blazor/host-and-deploy/app-base-path.md +++ b/aspnetcore/blazor/host-and-deploy/app-base-path.md @@ -218,7 +218,7 @@ In many hosting scenarios, the relative URL path to the app is the root of the a :::moniker-end > [!NOTE] -> When using (see ), [`app.UseRouting`](xref:Microsoft.AspNetCore.Builder.EndpointRoutingApplicationBuilderExtensions.UseRouting%2A) must be called after so that the Routing Middleware can observe the modified path before matching routes. Otherwise, routes are matched before the path is rewritten by as described in the [Middleware Ordering](xref:fundamentals/middleware/index#order) and [Routing](xref:fundamentals/routing) articles. +> When using (see ), [`app.UseRouting`](xref:Microsoft.AspNetCore.Builder.EndpointRoutingApplicationBuilderExtensions.UseRouting%2A) must be called after so that the Routing Middleware can observe the modified path before matching routes. Otherwise, routes are matched before the path is rewritten by as described in the and . Don't prefix links throughout the app with a forward slash. Either avoid the use of a path segment separator or use dot-slash (`./`) relative path notation: diff --git a/aspnetcore/data/ef-rp/update-related-data.md b/aspnetcore/data/ef-rp/update-related-data.md index 7bbb093802c8..8e1ddc463305 100644 --- a/aspnetcore/data/ef-rp/update-related-data.md +++ b/aspnetcore/data/ef-rp/update-related-data.md @@ -46,8 +46,6 @@ Update `Pages/Courses/Create.cshtml.cs` with the following code: [!code-csharp[](intro/samples/cu50/Pages/Courses/Create.cshtml.cs?highlight=7,18,27-41)] -[!INCLUDE[loc comments](~/includes/code-comments-loc.md)] - The preceding code: * Derives from `DepartmentNamePageModel`. @@ -269,8 +267,6 @@ Update `Pages/Courses/Create.cshtml.cs` with the following code: [!code-csharp[](intro/samples/cu30/Pages/Courses/Create.cshtml.cs?highlight=7,18,27-41)] -[!INCLUDE[about the series](~/includes/code-comments-loc.md)] - The preceding code: * Derives from `DepartmentNamePageModel`. diff --git a/aspnetcore/fundamentals/app-state.md b/aspnetcore/fundamentals/app-state.md index 68e5d0dfaaf4..cfbd7b1cd1d9 100644 --- a/aspnetcore/fundamentals/app-state.md +++ b/aspnetcore/fundamentals/app-state.md @@ -92,7 +92,7 @@ The following code shows how to set up the in-memory session provider with a def The preceding code sets a short timeout to simplify testing. -The order of middleware is important. Call `UseSession` after `UseRouting` and before `MapRazorPages` and `MapDefaultControllerRoute` . See [Middleware Ordering](xref:fundamentals/middleware/index#order). +The order of middleware is important. Call `UseSession` after `UseRouting` and before `MapRazorPages` and `MapDefaultControllerRoute`. See [Middleware Ordering](xref:fundamentals/middleware/index#middleware-order). [HttpContext.Session](xref:Microsoft.AspNetCore.Http.HttpContext.Session) is available after session state is configured. @@ -376,7 +376,7 @@ The following code shows how to set up the in-memory session provider with a def The preceding code sets a short timeout to simplify testing. -The order of middleware is important. Call `UseSession` after `UseRouting` and before `UseEndpoints`. See [Middleware Ordering](xref:fundamentals/middleware/index#order). +The order of middleware is important. Call `UseSession` after `UseRouting` and before `UseEndpoints`. For more information, see . [HttpContext.Session](xref:Microsoft.AspNetCore.Http.HttpContext.Session) is available after session state is configured. diff --git a/aspnetcore/fundamentals/http-requests.md b/aspnetcore/fundamentals/http-requests.md index def559cb6f3c..c5d44e61fecb 100644 --- a/aspnetcore/fundamentals/http-requests.md +++ b/aspnetcore/fundamentals/http-requests.md @@ -890,7 +890,6 @@ Typed clients: A typed client accepts an `HttpClient` parameter in its constructor: :::code language="csharp" source="http-requests/samples/3.x/HttpClientFactorySample/GitHub/GitHubService.cs" id="snippet1" highlight="5"::: -[!INCLUDE[about the series](~/includes/code-comments-loc.md)] In the preceding code: diff --git a/aspnetcore/fundamentals/localization/includes/localization35.md b/aspnetcore/fundamentals/localization/includes/localization35.md index ee9737598664..badfa25b2a3e 100644 --- a/aspnetcore/fundamentals/localization/includes/localization35.md +++ b/aspnetcore/fundamentals/localization/includes/localization35.md @@ -255,8 +255,6 @@ The current culture on a request is set in the localization [Middleware](xref:fu [!code-csharp[](~/fundamentals/localization/sample/3.x/Localization/Startup.cs?name=snippet2)] -[!INCLUDE[about the series](~/includes/code-comments-loc.md)] - `UseRequestLocalization` initializes a `RequestLocalizationOptions` object. On every request the list of `RequestCultureProvider` in the `RequestLocalizationOptions` is enumerated and the first provider that can successfully determine the request culture is used. The default providers come from the `RequestLocalizationOptions` class: 1. `QueryStringRequestCultureProvider` diff --git a/aspnetcore/fundamentals/middleware/index.md b/aspnetcore/fundamentals/middleware/index.md index 9c13018aadc7..7658f31e2d7c 100644 --- a/aspnetcore/fundamentals/middleware/index.md +++ b/aspnetcore/fundamentals/middleware/index.md @@ -1,42 +1,40 @@ --- title: ASP.NET Core Middleware +ai-usage: ai-assisted author: tdykstra description: Learn about ASP.NET Core middleware and the request pipeline. monikerRange: '>= aspnetcore-3.0' ms.author: tdykstra ms.custom: mvc -ms.date: 06/21/2025 +ms.date: 02/04/2026 uid: fundamentals/middleware/index -ms.ai: assisted --- # ASP.NET Core Middleware [!INCLUDE[](~/includes/not-latest-version.md)] -:::moniker range=">= aspnetcore-8.0" - -By [Rick Anderson](https://twitter.com/RickAndMSFT) and [Steve Smith](https://ardalis.com/) +Middleware is software that's assembled into an app pipeline to handle requests and responses. Each middleware: -Middleware is software that's assembled into an app pipeline to handle requests and responses. Each component: - -* Chooses whether to pass the request to the next component in the pipeline. -* Can perform work before and after the next component in the pipeline. +* Chooses whether to pass the request to the next middleware in the pipeline. +* Can perform work before and after the next middleware in the pipeline. Request delegates are used to build the request pipeline. The request delegates handle each HTTP request. -Request delegates are configured using , , and extension methods. An individual request delegate can be specified in-line as an anonymous method (called in-line middleware), or it can be defined in a reusable class. These reusable classes and in-line anonymous methods are *middleware*, also called *middleware components*. Each middleware component in the request pipeline is responsible for invoking the next component in the pipeline or short-circuiting the pipeline. When a middleware short-circuits, it's called a *terminal middleware* because it prevents further middleware from processing the request. +Request delegates are configured using , , and extension methods. An individual request delegate can be specified inline as an anonymous method (called inline middleware) or defined in a reusable class. These inline anonymous methods or reusable classes are called *middleware* or *middleware components*. Each middleware in the request pipeline is responsible for invoking the next middleware in the pipeline or short-circuiting the pipeline. When a middleware short-circuits, it's called a *terminal middleware* because it prevents further middleware from processing the request. - explains the difference between request pipelines in ASP.NET Core and ASP.NET 4.x and provides additional middleware samples. +For more information on the difference between request pipelines in ASP.NET Core and ASP.NET 4.x with additional middleware samples, see . -## The role of middleware by app type +## Role of middleware by app type -Blazor Web Apps, Razor Pages, and MVC process browser requests on the server with middleware. The guidance in this article applies to these types of apps. +Server-side Blazor, Razor Pages, and MVC process browser requests on the server with middleware. The guidance in this article applies to these types of apps. Standalone Blazor WebAssembly apps run entirely on the client and don't process requests with a middleware pipeline. The guidance in this article doesn't apply to standalone Blazor WebAssembly apps. ## Middleware code analysis -ASP.NET Core includes many compiler platform analyzers that inspect application code for quality. For more information, see +For more information on ASP.NET Core's compiler platform analyzers that inspect app code for quality, see . + +:::moniker range=">= aspnetcore-6.0" ## Create a middleware pipeline with `WebApplication` @@ -46,81 +44,671 @@ The ASP.NET Core request pipeline consists of a sequence of request delegates, c Each delegate can perform operations before and after the next delegate. Exception-handling delegates should be called early in the pipeline, so they can catch exceptions that occur in later stages of the pipeline. -The simplest possible ASP.NET Core app sets up a single request delegate that handles all requests. This case doesn't include an actual request pipeline. Instead, a single anonymous function is called in response to every HTTP request. +> [!NOTE] +> To experiment locally with the code examples in this section, create an ASP.NET Core app using the **ASP.NET Core Empty** project template. If using the .NET CLI, the template short name is `web` (`dotnet new web`). + +The simplest ASP.NET Core app calls to set up a single terminal middleware as an anonymous function request delegate to handle requests without a request pipeline. + +In the following example: + +* The call to is invoked on every request and writes ":::no-loc text="Hello world!":::" to the response. +* The call to at the end of the code block runs the app and blocks the calling thread until host shutdown. + +```csharp +var builder = WebApplication.CreateBuilder(args); +var app = builder.Build(); + +app.Run(async context => +{ + await context.Response.WriteAsync("Hello world!"); +}); + +app.Run(); +``` + +Response when accessing the app in a browser at its launch URL: + +> :::no-loc text="Hello world!"::: + +Chain multiple request delegates together with . The `next` parameter represents the next delegate in the pipeline. You can typically perform actions both before and after the `next` delegate. + +The following example demonstrates: + +* Two calls, each writing to the console: + * Where work can be performed that can write to the response (`context.Response`, ). + * Where work can be performed that doesn't write to the response after the `next` parameter is invoked. +* A terminal request delegate with a call to that writes ":::no-loc text="Hello world!":::" to the response. +* A final call, which never executes because it follows the terminal request delegate. +* A call to at the end of the code block to run the app and block the calling thread until host shutdown. + +```csharp +var builder = WebApplication.CreateBuilder(args); +var app = builder.Build(); + +app.Use(async (context, next) => +{ + Console.WriteLine("Work that can write to the response. (1)"); + await next.Invoke(context); + Console.WriteLine("Work that doesn't write to the response. (1)"); +}); + +app.Use(async (context, next) => +{ + Console.WriteLine("Work that can write to the response. (2)"); + await next.Invoke(context); + Console.WriteLine("Work that doesn't write to the response. (2)"); +}); + +app.Run(async context => +{ + await context.Response.WriteAsync("Hello world!"); +}); + +app.Use(async (context, next) => +{ + Console.WriteLine("This statement isn't reached. (3)"); + await next.Invoke(context); + Console.WriteLine("This statement isn't reached. (3)"); +}); + +app.Run(); +``` + +In the app's console window when the app is run: + + + +> :::no-loc text="Work that can write to the response. (1)"::: +> :::no-loc text="Work that can write to the response. (2)"::: +> :::no-loc text="Work that doesn't write to the response. (2)"::: +> :::no-loc text="Work that doesn't write to the response. (1)"::: + +*Short-circuiting* the request pipeline is often desirable because it avoids unnecessary work. For example, [Static File Middleware](xref:fundamentals/static-files) can act as a *terminal middleware* by processing a request for a static file and short-circuiting the rest of the pipeline. Middleware added to the pipeline before the terminal middleware still processes code after their `next.Invoke` statements. If you don't plan to call `next.Invoke` because your goal is to terminate the pipeline, use a [`Run` delegate](#run-delegate) instead of calling the extension method. + +Don't call `next.Invoke` during or after the response is sent to the client. After an is started, changes result in an exception. For example, [setting headers or a response status code throw an exception](xref:fundamentals/best-practices#do-not-modify-the-status-code-or-headers-after-the-response-body-has-started) after the response starts. Writing to the response body after calling `next` may: + +* Cause a protocol violation, such as writing more bytes to the response than the stated response's content length (`Content-Length` header value). +* Corrupt the body format, such as writing an HTML footer to a CSS file. + +To determine if the response has started, check the value of . + +For more information, see [Short-circuit middleware after routing](xref:fundamentals/routing#short-circuit-middleware-after-routing). + +## `Run` delegate + +A delegate doesn't receive a `next` parameter. The first `Run` delegate always terminates the pipeline. `Run` is also a convention, and some middleware may expose `Run` methods that execute at the end of the pipeline. + +Any or delegates after the first delegate aren't called. + +## Branch the middleware pipeline + + extensions are used as a convention to branch the request processing pipeline. branches the request pipeline based on matches of the given request path. If the request path starts with the given path, the branch is executed. + +In the following example, `HandleMap1` is called for requests to `/map1`, and `HandleMap2` is called for requests to `/map2`: + +```csharp +var builder = WebApplication.CreateBuilder(args); +var app = builder.Build(); + +app.Map("/map1", HandleMap1); +app.Map("/map2", HandleMap2); + +app.Run(async context => +{ + await context.Response.WriteAsync("Hello from the non-Map delegate!"); +}); + +app.Run(); + +private static void HandleMap1(IApplicationBuilder app) +{ + app.Run(async context => + { + await context.Response.WriteAsync("Map 1"); + }); +} + +private static void HandleMap2(IApplicationBuilder app) +{ + app.Run(async context => + { + await context.Response.WriteAsync("Map 2"); + }); +} +``` + +The following table shows the requests and responses using the preceding code. + +Request | Response +--- | --- +`/` | :::no-loc text="Hello from the non-Map delegate."::: +`/map1` | :::no-loc text="Map 1"::: +`/map2` | :::no-loc text="Map 2"::: +`/map3` | :::no-loc text="Hello from the non-Map delegate."::: + +When is used, the matched path segments are removed from and appended to for each request. + + can match multiple segments at once: + +```csharp +var builder = WebApplication.CreateBuilder(args); +var app = builder.Build(); + +app.Map("/map1/segment1", HandleMultipleSegments); + +app.Run(async context => +{ + await context.Response.WriteAsync("Hello from the non-Map delegate."); +}); + +app.Run(); + +private static void HandleMultipleSegments(IApplicationBuilder app) +{ + app.Run(async context => + { + await context.Response.WriteAsync("Processing '/map1/segment1'"); + }); +} +``` + +The following table shows the requests and responses using the preceding code. + +Request | Response +--- | --- +`/` | :::no-loc text="Hello from the non-Map delegate."::: +`/map1/segment1` | :::no-loc text="Processing '/map1/segment1'"::: + + supports nesting: + +```csharp +var builder = WebApplication.CreateBuilder(args); +var app = builder.Build(); + +app.Map("/level1", level1App => { + level1App.Map("/level2a", level2AApp => { + app.Run(async context => + { + await context.Response.WriteAsync("Processing '/level1/level2a'"); + }); + }); + level1App.Map("/level2b", level2BApp => { + app.Run(async context => + { + await context.Response.WriteAsync("Processing '/level1/level2b'"); + }); + }); +}); -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Middleware60/Program.cs)] +app.Run(async context => +{ + await context.Response.WriteAsync("Hello from the non-Map delegate!"); +}); + +app.Run(); +``` + +The following table shows the requests and responses using the preceding code. + +Request | Response +--- | --- +`/` | :::no-loc text="Hello from the non-Map delegate."::: +`/level1/level2a` | :::no-loc text="Processing '/level1/level2a'"::: +`/level1/level2b` | :::no-loc text="Processing '/level1/level2b'"::: + + branches the request pipeline based on the result of the given predicate. Any predicate of type `Func` can be used to map requests to a new branch of the pipeline. In the following example, a predicate is used to detect the presence of a query string variable named "`branch`": + +```csharp +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 the non-Map delegate."); +}); + +app.Run(); + +private static void HandleBranch(IApplicationBuilder app) +{ + app.Run(async context => + { + var branchVer = context.Request.Query["branch"]; + await context.Response.WriteAsync($"Branch used = '{branchVer}'"); + }); +} +``` + +The following table shows the requests and responses using the preceding code. + +Request | Response +--- | --- +`/` | :::no-loc text="Hello from the non-Map delegate."::: +`/?branch=main` | :::no-loc text="Branch used = 'main'"::: + + can branch the request pipeline based on the result of the given predicate. Unlike , the branch is rejoined to the main pipeline if it doesn't contain a terminal middleware: + +```csharp +var builder = WebApplication.CreateBuilder(args); +var app = builder.Build(); -Chain multiple request delegates together with . The `next` parameter represents the next delegate in the pipeline. You can short-circuit the pipeline by *not* calling the `next` parameter. You can typically perform actions both before and after the `next` delegate, as the following example demonstrates: +app.UseWhen(context => context.Request.Query.ContainsKey("branch"), + appBuilder => HandleBranchAndRejoin(appBuilder)); -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain60/Program.cs?highlight=4-9)] +app.Run(async context => +{ + await context.Response.WriteAsync("Hello from the non-Map delegate."); +}); + +app.Run(); + +void HandleBranchAndRejoin(IApplicationBuilder app) +{ + var logger = app.ApplicationServices.GetRequiredService>(); -### Short-circuiting the request pipeline + app.Use(async (context, next) => + { + var branchVer = context.Request.Query["branch"]; + logger.LogInformation("Branch used = {branchVer}", branchVer.ToString()); + + Console.WriteLine("Work that can write to the response."); + await next.Invoke(context); + Console.WriteLine("Work that doesn't write to the response."); + }); +} +``` + +In the preceding example, a response of ":::no-loc text="Hello from the non-Map delegate.":::" is written for all requests. If the request includes a query string variable named "`branch`," its value is logged before the main pipeline is rejoined. + +:::moniker-end + +:::moniker range="< aspnetcore-6.0" + +## Create a middleware pipeline with `IApplicationBuilder` + +The ASP.NET Core request pipeline consists of a sequence of request delegates, called one after the other. The following diagram demonstrates the concept. The thread of execution follows the black arrows. + +![Request processing pattern showing a request arriving, processing through three middlewares, and the response leaving the app. Each middleware runs its logic and hands off the request to the next middleware at the next() statement. After the third middleware processes the request, the request passes back through the prior two middlewares in reverse order for additional processing after their next() statements before leaving the app as a response to the client.](~/fundamentals/middleware/index/_static/request-delegate-pipeline.png) + +Each delegate can perform operations before and after the next delegate. Exception-handling delegates should be called early in the pipeline, so they can catch exceptions that occur in later stages of the pipeline. + +The simplest possible ASP.NET Core app sets up a single request delegate that handles all requests. This case doesn't include an actual request pipeline. Instead, a single anonymous function is called in response to every HTTP request. + +```csharp +public class Startup +{ + public void Configure(IApplicationBuilder app) + { + app.Run(async context => + { + await context.Response.WriteAsync("Hello, World!"); + }); + } +} +``` + +Chain multiple request delegates together with . The `next` parameter represents the next delegate in the pipeline. You can short-circuit the pipeline by *not* calling the *next* parameter. You can typically perform actions both before and after the next delegate, as the following example demonstrates: + +```csharp +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. +}); +``` When a delegate doesn't pass a request to the next delegate, it's called *short-circuiting the request pipeline*. Short-circuiting is often desirable because it avoids unnecessary work. For example, [Static File Middleware](xref:fundamentals/static-files) can act as a *terminal middleware* by processing a request for a static file and short-circuiting the rest of the pipeline. Middleware added to the pipeline before the middleware that terminates further processing still processes code after their `next.Invoke` statements. However, see the following warning about attempting to write to a response that has already been sent. > [!WARNING] -> Don't call `next.Invoke` during or after the response has been sent to the client. After an has started, changes result in an exception. For example, [setting headers and a status code throw an exception](xref:fundamentals/best-practices#do-not-modify-the-status-code-or-headers-after-the-response-body-has-started) after the response starts. Writing to the response body after calling `next`: +> Don't call `next.Invoke` after the response has been sent to the client. Changes to after the response has started throw an exception. For example, [setting headers and a status code throw an exception](xref:fundamentals/best-practices#do-not-modify-the-status-code-or-headers-after-the-response-body-has-started). Writing to the response body after calling `next`: > -> * May cause a protocol violation, such as writing more than the stated `Content-Length`. -> * May corrupt the body format, such as writing an HTML footer to a CSS file. +> * May cause a protocol violation. For example, writing more than the stated `Content-Length`. +> * May corrupt the body format. For example, writing an HTML footer to a CSS file. > > is a useful hint to indicate if headers have been sent or the body has been written to. -For more information, see [Short-circuit middleware after routing](xref:fundamentals/routing#short-circuit-middleware-after-routing). - -### `Run` delegates - delegates don't receive a `next` parameter. The first `Run` delegate is always terminal and terminates the pipeline. `Run` is a convention. Some middleware components may expose `Run[Middleware]` methods that run at the end of the pipeline: -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain60/Program.cs?highlight=11-14)] -[!INCLUDE[about the series](~/includes/code-comments-loc.md)] +```csharp +app.Run(async context => +{ + await context.Response.WriteAsync("Hello from 2nd delegate."); +}); +``` In the preceding example, the `Run` delegate writes `"Hello from 2nd delegate."` to the response and then terminates the pipeline. If another `Use` or `Run` delegate is added after the `Run` delegate, it's not called. -### Prefer app.Use overload that requires passing the context to next +## Branch the middleware pipeline + + extensions are used as a convention for branching the pipeline. `Map` branches the request pipeline based on matches of the given request path. If the request path starts with the given path, the branch is executed. + +```csharp +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."); + }); + } +} +``` - +The following table shows the requests and responses from `http://localhost:1234` using the previous code. -The non-allocating [app.Use](xref:Microsoft.AspNetCore.Builder.IApplicationBuilder.Use%2A) extension method: +| Request | 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. | + +When `Map` is used, the matched path segments are removed from `HttpRequest.Path` and appended to `HttpRequest.PathBase` for each request. -* Requires passing the context to `next`. -* Saves two internal per-request allocations that are required when using the other overload. +`Map` supports nesting, for example: -For more information, see [this GitHub issue](https://github.com/dotnet/aspnetcore/pull/31784). +```csharp +app.Map("/level1", level1App => { + level1App.Map("/level2a", level2AApp => { + // "/level1/level2a" processing + }); + level1App.Map("/level2b", level2BApp => { + // "/level1/level2b" processing + }); +}); +``` - +`Map` can also match multiple segments at once: + +```csharp +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."); + }); + } +} +``` + + branches the request pipeline based on the result of the given predicate. Any predicate of type `Func` can be used to map requests to a new branch of the pipeline. In the following example, a predicate is used to detect the presence of a query string variable `branch`: + +```csharp +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."); + }); + } +} +``` + +The following table shows the requests and responses from `http://localhost:1234` using the previous code: + +| Request | Response | +| ----------------------------- | ---------------------------- | +| localhost:1234 | Hello from non-Map delegate. | +| localhost:1234/?branch=main | Branch used = main | + + also branches the request pipeline based on the result of the given predicate. Unlike with `MapWhen`, this branch is rejoined to the main pipeline if it doesn't short-circuit or contain a terminal middleware: + +```csharp +public class Startup +{ + private void HandleBranchAndRejoin(IApplicationBuilder app, ILogger logger) + { + app.Use(async (context, next) => + { + var branchVer = context.Request.Query["branch"]; + logger.LogInformation("Branch used = {branchVer}", branchVer.ToString()); + + // 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 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."); + }); + } +} +``` + +In the preceding example, a response of "Hello from main pipeline." is written for all requests. If the request includes a query string variable `branch`, its value is logged before the main pipeline is rejoined. + +:::moniker-end ## Middleware order -The following diagram shows the complete request processing pipeline for ASP.NET Core MVC and Razor Pages apps. You can see how, in a typical app, existing middlewares are ordered and where custom middlewares are added. You have full control over how to reorder existing middlewares or inject new custom middlewares as necessary for your scenarios. +:::moniker range=">= aspnetcore-8.0" -![ASP.NET Core middleware pipeline](~/fundamentals/middleware/index/_static/middleware-pipeline.svg) +The order that middleware appears in the app's `Program` file defines the order in which middleware are invoked on a request with the reverse order for the response. - + +Typical Blazor Web App middleware pipeline: + +```csharp +app.UseWebAssemblyDebugging(); // Development environment with client-side rendering +app.UseMigrationsEndPoint(); // Development environment with ASP.NET Core Identity + +app.UseExceptionHandler("/Error", createScopeForErrors: true); // Non-Development environment +app.UseHsts(); // Non-Development environment with HTTPS protocol + +app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true); + +app.UseHttpsRedirection(); // With HTTPS protocol + +app.UseAntiforgery(); + +app.MapStaticAssets(); + +app.MapRazorComponents(); // With additional extension methods for render modes + +app.MapAdditionalIdentityEndpoints(); // With ASP.NET Core Identity + +app.Run(); +``` + +Typical Razor Pages/MVC middleware pipeline: + +```csharp +app.UseMigrationsEndPoint(); // Development environment with ASP.NET Core Identity + +app.UseExceptionHandler("/Error"); // Non-Development environment +app.UseHsts(); // Non-Development environment with HTTPS protocol + +app.UseHttpsRedirection(); // With HTTPS protocol + +// app.UseCookiePolicy(); +app.UseRouting(); // If not called, runs at the beginning of the pipeline by default +// app.UseRateLimiter(); +// app.UseRequestLocalization(); +// app.UseCors(); + +// app.UseAuthentication(); // Called internally for ASP.NET Core Identity +app.UseAuthorization(); +// app.UseSession(); +// app.UseResponseCompression(); +// app.UseResponseCaching(); + +app.MapStaticAssets(); + +app.MapControllerRoute(...); // For MVC controllers + +app.MapRazorPages(); // For Razor Pages pages + +app.MapControllers(); // With authentication in a Razor Pages app + +app.Run(); +``` + +In the preceding code: + +* CORS Middleware (), Authentication Middleware (), and Authorization Middleware () must appear in the order shown. +* CORS Middleware () must appear before Response Caching Middleware () to add CORS headers on every request, including cached responses. For more information, see [It is not clear that UseCORS must come before UseResponseCaching (`dotnet/aspnetcore` #23218](https://github.com/dotnet/aspnetcore/issues/23218). +* Request Localization Middleware () must appear before any middleware that might check the request culture, for example, Static File Middleware (). +* Rate Limiting Middleware () must be called after Routing Middleware () when rate limiting endpoint-specific APIs are used. For example, if the [`[EnableRateLimiting]` attribute](xref:Microsoft.AspNetCore.RateLimiting.EnableRateLimitingAttribute) is used, Rate Limiting Middleware must be called after Routing Middleware. When calling only global limiters, Rate Limiting Middleware can be called before Routing Middleware. + +In some scenarios, middleware has different ordering. For example, caching and compression ordering depends on the app's specification. In the following order, CPU usage might be reduced by caching the compressed response, but the app might end up caching multiple representations of a resource using different compression algorithms, such as Gzip or Brotli: + +```csharp +app.UseResponseCaching(); +app.UseResponseCompression(); +``` + +Static assets are typically served early in the pipeline so that the app can short-circuit request processing to improve performance. + +Authentication doesn't short-circuit unauthenticated requests. Although Authentication Middleware authenticates requests, authorization occurs after the framework selects a Razor component in a Blazor Web App, a page in a Razor Pages app, or a controller and action in an MVC app. + +:::moniker-end + +:::moniker range=">= aspnetcore-7.0 < aspnetcore-8.0" + +The following diagram shows the complete request processing pipeline for ASP.NET Core MVC and Razor Pages apps. You can see how, in a typical app, existing middlewares are ordered and where custom middlewares are added. You have full control over how to reorder existing middlewares or inject new custom middlewares as necessary for your scenarios. + +![ASP.NET Core middleware pipeline](~/fundamentals/middleware/index/_static/middleware-pipeline.svg) The **Endpoint** middleware in the preceding diagram executes the filter pipeline for the corresponding app type—MVC or Razor Pages. The **Routing** middleware in the preceding diagram is shown following **Static Files**. This is the order that the project templates implement by explicitly calling [app.UseRouting](xref:Microsoft.AspNetCore.Builder.EndpointRoutingApplicationBuilderExtensions.UseRouting%2A). If you don't call `app.UseRouting`, the **Routing** middleware runs at the beginning of the pipeline by default. For more information, see [Routing](xref:fundamentals/routing). -![ASP.NET Core filter pipeline](~/fundamentals/middleware/index/_static/mvc-endpoint.svg) - The order that middleware components are added in the `Program.cs` file defines the order in which the middleware components are invoked on requests and the reverse order for the response. The order is **critical** for security, performance, and functionality. The following highlighted code in `Program.cs` adds security-related middleware components in the typical recommended order: -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Program70All3.cs?highlight=19-44)] +```csharp +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(options => + options.UseSqlServer(connectionString)); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); + +builder.Services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) + .AddEntityFrameworkStores(); +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(); +``` In the preceding code: @@ -208,106 +796,381 @@ app.UseResponseCompression(); app.MapRazorPages(); ``` -For information about Single Page Applications, see . +:::moniker-end -## UseCors and UseStaticFiles order +:::moniker range=">= aspnetcore-6.0 < aspnetcore-7.0" -The order for calling `UseCors` and `UseStaticFiles` depends on the app. For more information, see [UseCors and UseStaticFiles order](xref:security/cors#uc1) +The following diagram shows the complete request processing pipeline for ASP.NET Core MVC and Razor Pages apps. You can see how, in a typical app, existing middlewares are ordered and where custom middlewares are added. You have full control over how to reorder existing middlewares or inject new custom middlewares as necessary for your scenarios. -### Forwarded Headers Middleware order +![ASP.NET Core middleware pipeline](~/fundamentals/middleware/index/_static/middleware-pipeline.svg) -[!INCLUDE[](~/includes/ForwardedHeaders.md)] +The **Endpoint** middleware in the preceding diagram executes the filter pipeline for the corresponding app type—MVC or Razor Pages. -## Branch the middleware pipeline +The **Routing** middleware in the preceding diagram is shown following **Static Files**. This is the order that the project templates implement by explicitly calling [app.UseRouting](xref:Microsoft.AspNetCore.Builder.EndpointRoutingApplicationBuilderExtensions.UseRouting%2A). If you don't call `app.UseRouting`, the **Routing** middleware runs at the beginning of the pipeline by default. For more information, see [Routing](xref:fundamentals/routing). - extensions are used as a convention for branching the pipeline. `Map` branches the request pipeline based on matches of the given request path. If the request path starts with the given path, the branch is executed. +The order that middleware components are added in the `Program.cs` file defines the order in which the middleware components are invoked on requests and the reverse order for the response. The order is **critical** for security, performance, and functionality. -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain60/ProgramMap.cs)] +The following highlighted code in `Program.cs` adds security-related middleware components in the typical recommended order: -The following table shows the requests and responses from `http://localhost:1234` using the preceding code. +```csharp +using IndividualAccountsExample.Data; +using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; -| Request | 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. | +var builder = WebApplication.CreateBuilder(args); -When `Map` is used, the matched path segments are removed from `HttpRequest.Path` and appended to `HttpRequest.PathBase` for each request. +// Add services to the container. +var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); +builder.Services.AddDbContext(options => + options.UseSqlServer(connectionString)); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); -`Map` supports nesting, for example: +builder.Services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) + .AddEntityFrameworkStores(); +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(); +``` + +In the preceding code: + +* Middleware that is not added when creating a new web app with [individual users accounts](xref:security/authentication/identity) is commented out. +* Not every middleware appears in this exact order, but many do. For example: + * `UseCors`, `UseAuthentication`, and `UseAuthorization` must appear in the order shown. + * `UseCors` currently must appear before `UseResponseCaching`. This requirement is explained in [GitHub issue dotnet/aspnetcore #23218](https://github.com/dotnet/aspnetcore/issues/23218). + * `UseRequestLocalization` must appear before any middleware that might check the request culture (for example, `app.UseMvcWithDefaultRoute()`). + +In some scenarios, middleware has different ordering. For example, caching and compression ordering is scenario specific, and there are multiple valid orderings. For example: ```csharp -app.Map("/level1", level1App => { - level1App.Map("/level2a", level2AApp => { - // "/level1/level2a" processing +app.UseResponseCaching(); +app.UseResponseCompression(); +``` + +With the preceding code, CPU usage could be reduced by caching the compressed response, but you might end up caching multiple representations of a resource using different compression algorithms such as Gzip or Brotli. + +The following ordering combines static files to allow caching compressed static files: + +```csharp +app.UseResponseCaching(); +app.UseResponseCompression(); +app.UseStaticFiles(); +``` + +The following `Program.cs` code adds middleware components for common app scenarios: + +1. Exception/error handling + * When the app runs in the `Development` environment: + * Developer Exception Page Middleware () reports app runtime errors. + * Database Error Page Middleware () reports database runtime errors. + * When the app runs in the `Production` environment: + * Exception Handler Middleware () catches exceptions thrown in the following middlewares. + * HTTP Strict Transport Security Protocol (HSTS) Middleware () adds the `Strict-Transport-Security` header. +1. HTTPS Redirection Middleware () redirects HTTP requests to HTTPS. +1. Static File Middleware () returns static files and short-circuits further request processing. +1. Cookie Policy Middleware () conforms the app to the EU General Data Protection Regulation (GDPR) regulations. +1. Routing Middleware () to route requests. +1. Authentication Middleware () attempts to authenticate the user before they're allowed access to secure resources. +1. Authorization Middleware () authorizes a user to access secure resources. +1. Session Middleware () establishes and maintains session state. If the app uses session state, call Session Middleware after Cookie Policy Middleware and before MVC Middleware. +1. Endpoint Routing Middleware ( with ) to add Razor Pages endpoints to the request pipeline. + +```csharp +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(); +``` + +In the preceding example code, each middleware extension method is exposed on through the namespace. + + is the first middleware component added to the pipeline. Therefore, the Exception Handler Middleware catches any exceptions that occur in later calls. + +Static File Middleware is called early in the pipeline so that it can handle requests and short-circuit without going through the remaining components. The Static File Middleware provides **no** authorization checks. Any files served by Static File Middleware, including those under *wwwroot*, are publicly available. For an approach to secure static files, see . + +If the request isn't handled by the Static File Middleware, it's passed on to the Authentication Middleware (), which performs authentication. Authentication doesn't short-circuit unauthenticated requests. Although Authentication Middleware authenticates requests, authorization (and rejection) occurs only after MVC selects a specific Razor Page or MVC controller and action. + +The following example demonstrates a middleware order where requests for static files are handled by Static File Middleware before Response Compression Middleware. Static files aren't compressed with this middleware order. The Razor Pages responses can be compressed. + +```csharp +// Static files aren't compressed by Static File Middleware. +app.UseStaticFiles(); + +app.UseRouting(); + +app.UseResponseCompression(); + +app.MapRazorPages(); +``` + +:::moniker-end + +:::moniker range="< aspnetcore-6.0" + +The following diagram shows the complete request processing pipeline for ASP.NET Core MVC and Razor Pages apps. You can see how, in a typical app, existing middlewares are ordered and where custom middlewares are added. You have full control over how to reorder existing middlewares or inject new custom middlewares as necessary for your scenarios. + +![ASP.NET Core middleware pipeline](~/fundamentals/middleware/index/_static/middleware-pipeline.svg) + +The **Endpoint** middleware in the preceding diagram executes the filter pipeline for the corresponding app type—MVC or Razor Pages. + +The order that middleware components are added in the `Startup.Configure` method defines the order in which the middleware components are invoked on requests and the reverse order for the response. The order is **critical** for security, performance, and functionality. + +The following `Startup.Configure` method adds security-related middleware components in the typical recommended order: + +```csharp +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?}"); }); - level1App.Map("/level2b", level2BApp => { - // "/level1/level2b" processing +} +``` + +In the preceding code: + +* Middleware that is not added when creating a new web app with [individual users accounts](xref:security/authentication/identity) is commented out. +* Not every middleware appears in this exact order, but many do. For example: + * `UseCors`, `UseAuthentication`, and `UseAuthorization` must appear in the order shown. + * `UseCors` currently must appear before `UseResponseCaching` due to [this bug](https://github.com/dotnet/aspnetcore/issues/23218). + * `UseRequestLocalization` must appear before any middleware that might check the request culture (for example, `app.UseMvcWithDefaultRoute()`). + +In some scenarios, middleware has different ordering. For example, caching and compression ordering is scenario specific, and there's multiple valid orderings. For example: + +```csharp +app.UseResponseCaching(); +app.UseResponseCompression(); +``` + +With the preceding code, CPU could be saved by caching the compressed response, but you might end up caching multiple representations of a resource using different compression algorithms such as Gzip or Brotli. + +The following ordering combines static files to allow caching compressed static files: + +```csharp +app.UseResponseCaching(); +app.UseResponseCompression(); +app.UseStaticFiles(); +``` + +The following `Startup.Configure` method adds middleware components for common app scenarios: + +1. Exception/error handling + * When the app runs in the `Development` environment: + * Developer Exception Page Middleware () reports app runtime errors. + * Database Error Page Middleware reports database runtime errors. + * When the app runs in the `Production` environment: + * Exception Handler Middleware () catches exceptions thrown in the following middlewares. + * HTTP Strict Transport Security Protocol (HSTS) Middleware () adds the `Strict-Transport-Security` header. +1. HTTPS Redirection Middleware () redirects HTTP requests to HTTPS. +1. Static File Middleware () returns static files and short-circuits further request processing. +1. Cookie Policy Middleware () conforms the app to the EU General Data Protection Regulation (GDPR) regulations. +1. Routing Middleware () to route requests. +1. Authentication Middleware () attempts to authenticate the user before they're allowed access to secure resources. +1. Authorization Middleware () authorizes a user to access secure resources. +1. Session Middleware () establishes and maintains session state. If the app uses session state, call Session Middleware after Cookie Policy Middleware and before MVC Middleware. +1. Endpoint Routing Middleware ( with ) to add Razor Pages endpoints to the request pipeline. + +```csharp +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(); }); -}); +} ``` -`Map` can also match multiple segments at once: +In the preceding example code, each middleware extension method is exposed on through the namespace. -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain60/ProgramMultiSeg.cs?highlight=4)] + is the first middleware component added to the pipeline. Therefore, the Exception Handler Middleware catches any exceptions that occur in later calls. - branches the request pipeline based on the result of the given predicate. Any predicate of type `Func` can be used to map requests to a new branch of the pipeline. In the following example, a predicate is used to detect the presence of a query string variable `branch`: +Static File Middleware is called early in the pipeline so that it can handle requests and short-circuit without going through the remaining components. The Static File Middleware provides **no** authorization checks. Any files served by Static File Middleware, including those under *wwwroot*, are publicly available. For an approach to secure static files, see . + +If the request isn't handled by the Static File Middleware, it's passed on to the Authentication Middleware (), which performs authentication. Authentication doesn't short-circuit unauthenticated requests. Although Authentication Middleware authenticates requests, authorization (and rejection) occurs only after MVC selects a specific Razor Page or MVC controller and action. -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain60/ProgramMapWhen.cs?highlight=4)] +The following example demonstrates a middleware order where requests for static files are handled by Static File Middleware before Response Compression Middleware. Static files aren't compressed with this middleware order. The Razor Pages responses can be compressed. -The following table shows the requests and responses from `http://localhost:1234` using the previous code: +```csharp +public void Configure(IApplicationBuilder app) +{ + // Static files aren't compressed by Static File Middleware. + app.UseStaticFiles(); -| Request | Response | -| ----------------------------- | ------------------------------ | -| `localhost:1234` | `Hello from non-Map delegate.` | -| `localhost:1234/?branch=main` | `Branch used = main` | + app.UseRouting(); - also branches the request pipeline based on the result of the given predicate. Unlike with `MapWhen`, this branch is rejoined to the main pipeline if it doesn't contain a terminal middleware: + app.UseResponseCompression(); -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain60/ProgramUseWhen.cs?highlight=4-5)] + app.UseEndpoints(endpoints => + { + endpoints.MapRazorPages(); + }); +} +``` -In the preceding example, a response of `Hello from non-Map delegate.` is written for all requests. If the request includes a query string variable `branch`, its value is logged before the main pipeline is rejoined. +For Single Page Applications (SPAs), the SPA middleware usually comes last in the middleware pipeline. The SPA middleware comes last: + +* To allow all other middlewares to respond to matching requests first. +* To allow SPAs with client-side routing to run for all routes that are unrecognized by the server app. + +For more details on SPAs, see the guides for the [React](xref:spa/react) and [Angular](xref:spa/angular) project templates. + +:::moniker-end + +For information about Single Page Applications, see the guides for the [React](xref:spa/react) and [Angular](xref:spa/angular) project templates. + +## `UseCors` and `UseStaticFiles` order + +For more information on ordering and , see . + +## Forwarded Headers Middleware order + +Run Forwarded Headers Middleware before other middleware to ensure that the middleware relying on forwarded headers information can consume the header values for processing. To run Forwarded Headers Middleware after Diagnostics and Error Handling Middleware, see [Forwarded Headers Middleware order](xref:host-and-deploy/proxy-load-balancer#forwarded-headers-middleware-order). ## Built-in middleware -ASP.NET Core ships with the following middleware components. The *Order* column provides notes on middleware placement in the request processing pipeline and under what conditions the middleware may terminate request processing. When a middleware short-circuits the request processing pipeline and prevents further downstream middleware from processing a request, it's called a *terminal middleware*. For more information on short-circuiting, see the [Create a middleware pipeline with WebApplication](#create-a-middleware-pipeline-with-webapplication) section. - -| Middleware | Description | Order | -| ---------- | ----------- | ----- | -| [Antiforgery](xref:security/anti-request-forgery) | Provides anti-request-forgery support. | After authentication and authorization, before endpoints. | -| [Authentication](xref:security/authentication/identity) | Provides authentication support. | Before `HttpContext.User` is needed. Terminal for OAuth callbacks. | -| [Authorization](xref:Microsoft.AspNetCore.Builder.AuthorizationAppBuilderExtensions.UseAuthorization%2A) | Provides authorization support. | Immediately after the Authentication Middleware. | -| [Cookie Policy](xref:security/gdpr) | Tracks consent from users for storing personal information and enforces minimum standards for cookie fields, such as `secure` and `SameSite`. | Before middleware that issues cookies. Examples: Authentication, Session, MVC (TempData). | -| [CORS](xref:security/cors) | Configures Cross-Origin Resource Sharing. | Before components that use CORS. `UseCors` currently must go before `UseResponseCaching` due to [this bug](https://github.com/dotnet/aspnetcore/issues/23218).| -| [DeveloperExceptionPage](xref:Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware) | Generates a page with error information that is intended for use only in the `Development` environment. | Before components that generate errors. The project templates automatically register this middleware as the first middleware in the pipeline when the environment is `Development`. | -| [Diagnostics](xref:fundamentals/error-handling) | Several separate middlewares that provide a developer exception page, exception handling, status code pages, and the default web page for new apps. | Before components that generate errors. Terminal for exceptions or serving the default web page for new apps. | -| [Forwarded Headers](xref:host-and-deploy/proxy-load-balancer) | Forwards proxied headers onto the current request. | Before components that consume the updated fields. Examples: scheme, host, client IP, method. | -| [Health Check](xref:host-and-deploy/health-checks) | Checks the health of an ASP.NET Core app and its dependencies, such as checking database availability. | Terminal if a request matches a health check endpoint. | -| [Header Propagation](xref:fundamentals/http-requests#header-propagation-middleware) | Propagates HTTP headers from the incoming request to the outgoing HTTP Client requests. | -| [HTTP Logging](xref:fundamentals/http-logging/index) | Logs HTTP Requests and Responses. | At the beginning of the middleware pipeline. | -| [HTTP Method Override](xref:Microsoft.AspNetCore.Builder.HttpMethodOverrideExtensions) | Allows an incoming POST request to override the method. | Before components that consume the updated method. | -| [HTTPS Redirection](xref:security/enforcing-ssl#require-https) | Redirect all HTTP requests to HTTPS. | Before components that consume the URL. | -| [HTTP Strict Transport Security (HSTS)](xref:security/enforcing-ssl#http-strict-transport-security-protocol-hsts) | Security enhancement middleware that adds a special response header. | Before responses are sent and after components that modify requests. Examples: Forwarded Headers, URL Rewriting. | -| [MVC](xref:mvc/overview) | Processes requests with MVC/Razor Pages. | Terminal if a request matches a route. | -| [OWIN](xref:fundamentals/owin) | Interop with OWIN-based apps, servers, and middleware. | Terminal if the OWIN Middleware fully processes the request. | -| [Output Caching](xref:performance/caching/output) | Provides support for caching responses based on configuration. | Before components that require caching. `UseRouting` must come before `UseOutputCaching`. `UseCORS` must come before `UseOutputCaching`.| -| [Response Caching](xref:performance/caching/middleware) | Provides support for caching responses. This requires client participation to work. Use output caching for complete server control. | Before components that require caching. `UseCORS` must come before `UseResponseCaching`. Is typically not beneficial for UI apps such as Razor Pages because browsers generally set request headers that prevent caching. [Output caching](xref:performance/caching/output) benefits UI apps.| -| [Request Decompression](xref:fundamentals/middleware/request-decompression) | Provides support for decompressing requests. | Before components that read the request body. | -| [Response Compression](xref:performance/response-compression) | Provides support for compressing responses. | Before components that require compression. | -| [Request Localization](xref:fundamentals/localization) | Provides localization support. | Before localization sensitive components. Must appear after Routing Middleware when using . | -| [Request Timeouts](xref:performance/timeouts) | Provides support for configuring request timeouts, global and per endpoint. | `UseRequestTimeouts` must come after `UseExceptionHandler`, `UseDeveloperExceptionPage`, and `UseRouting`. | -| [Endpoint Routing](xref:fundamentals/routing) | Defines and constrains request routes. | Terminal for matching routes. | -| [SPA](xref:Microsoft.AspNetCore.Builder.SpaApplicationBuilderExtensions.UseSpa%2A) | Handles all requests from this point in the middleware chain by returning the default page for the Single Page Application (SPA) | Late in the chain, so that other middleware for serving static files, MVC actions, etc., takes precedence.| -| [Session](xref:fundamentals/app-state) | Provides support for managing user sessions. | Before components that require Session. | -| [Static Files](xref:fundamentals/static-files) | Provides support for serving static files and directory browsing. | Terminal if a request matches a file. | -| [URL Rewrite](xref:fundamentals/url-rewriting) | Provides support for rewriting URLs and redirecting requests. | Before components that consume the URL. | -| [W3CLogging](xref:fundamentals/w3c-logger/index) | Generates server access logs in the [W3C Extended Log File Format](https://www.w3.org/TR/WD-logfile.html). | At the beginning of the middleware pipeline. | -| [WebSockets](xref:fundamentals/websockets) | Enables the WebSockets protocol. | Before components that are required to accept WebSocket requests. | +The latest release of ASP.NET Core ships with the following middleware. The *UI stack* column indicates the typical UI stack where the middleware is used [All, Blazor Web App (BWA), Razor Pages and MVC (RP/MVC)]. The *Order* column provides notes on middleware placement in the request processing pipeline and under what conditions the middleware may terminate request processing. When a middleware short-circuits the request processing pipeline and prevents further downstream middleware from processing a request, it's called a *terminal middleware*. For more information on short-circuiting, see the [Create a middleware pipeline with `WebApplication`](#create-a-middleware-pipeline-with-webapplication) section. + + + +Middleware | Description | UI stack | Order +--- | --- | --- | --- +[Antiforgery](xref:security/anti-request-forgery) | Provides anti-request-forgery support. | All | After authentication and authorization, before endpoints. +[Authentication](xref:security/authentication/identity) | Provides authentication support. | All | Before `HttpContext.User` is required. Terminal for OAuth callbacks. +[Authorization](xref:Microsoft.AspNetCore.Builder.AuthorizationAppBuilderExtensions.UseAuthorization%2A) | Provides authorization support. | All | Immediately after the Authentication Middleware. +[Cookie Policy](xref:security/gdpr) | Tracks consent from users for storing personal information and enforces minimum standards for cookie fields, such as `secure` and `SameSite`. | All | Before middleware that issues cookies. Examples: Authentication, Session, MVC (TempData). +[CORS](xref:security/cors) | Configures Cross-Origin Resource Sharing. | All | Before middleware that use CORS. must go before . For more information, see [It is not clear that UseCORS must come before UseResponseCaching (`dotnet/aspnetcore` #23218](https://github.com/dotnet/aspnetcore/issues/23218). +[Developer Exception Page](xref:Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware) | Generates a page with error information that is intended for use only in the `Development` environment. | All | Before middleware that generate errors. The project templates automatically register this middleware as the first middleware in the pipeline when the environment is `Development`. +[Diagnostics](xref:fundamentals/error-handling) | Several separate middlewares that provide a developer exception page, exception handling, status code pages, and the default web page for new apps. | All | Before middleware that generate errors. Terminal for exceptions or serving the default web page for new apps. +[Forwarded Headers](xref:host-and-deploy/proxy-load-balancer) | Forwards proxied headers onto the current request. | All | Before middleware that consume the updated fields. Examples: scheme, host, client IP, method. +[Health Check](xref:host-and-deploy/health-checks) | Checks the health of an ASP.NET Core app and its dependencies, such as checking database availability. | All | Terminal if a request matches a health check endpoint. +[Header Propagation](xref:fundamentals/http-requests#header-propagation-middleware) | Propagates HTTP headers from the incoming request to the outgoing HTTP Client requests. | +All | +[HTTP Logging](xref:fundamentals/http-logging/index) | Logs HTTP Requests and Responses. | All | At the beginning of the middleware pipeline. +[HTTP Method Override](xref:Microsoft.AspNetCore.Builder.HttpMethodOverrideExtensions) | Allows an incoming POST request to override the method. | All | Before middleware that consume the updated method. +[HTTPS Redirection](xref:security/enforcing-ssl#require-https) | Redirect all HTTP requests to HTTPS. | All | Before middleware that consume the URL. +[HTTP Strict Transport Security (HSTS)](xref:security/enforcing-ssl#http-strict-transport-security-protocol-hsts) | Security enhancement middleware that adds a special response header. | All | Before responses are sent and after middleware that modify requests. Examples: Forwarded Headers, URL Rewriting. +[MVC](xref:mvc/overview) | Processes requests with MVC/Razor Pages. | RP/MVC | Terminal if a request matches a route. +[OWIN](xref:fundamentals/owin) | Interop with OWIN-based apps, servers, and middleware. | RP/MVC | Terminal if the OWIN Middleware fully processes the request. +[Output Caching](xref:performance/caching/output) | Provides support for caching responses based on configuration. | RP/MVC | Before middleware that require caching. and must come before . +[Response Caching](xref:performance/caching/middleware) | Provides support for caching responses. This requires client participation to work. Use output caching for complete server control. | RP/MVC | Before middleware that require caching. must come before . Response caching isn't typically beneficial for UI apps, such as Razor Pages, because browsers generally set request headers that prevent caching. [Output caching](xref:performance/caching/output) benefits UI apps. +[Request Decompression](xref:fundamentals/middleware/request-decompression) | Provides support for decompressing requests. | All | Before middleware that read the request body. +[Response Compression](xref:performance/response-compression) | Provides support for compressing responses. | All | Before middleware that require compression. +[Request Localization](xref:fundamentals/localization) | Provides localization support. | All | Before localization sensitive middleware. Must appear after Routing Middleware when using . +[Request Timeouts](xref:performance/timeouts) | Provides support for configuring request timeouts, global and per endpoint. | All | must come after , , and . +[Endpoint Routing](xref:fundamentals/routing). | Defines and constrains request routes. | All | Terminal for matching routes. +[SPA](xref:Microsoft.AspNetCore.Builder.SpaApplicationBuilderExtensions.UseSpa%2A) | Handles all requests from this point in the middleware chain by returning the default page for the Single Page Application (SPA). | All | Appears late in the pipeline, so other middleware for serving static files, such as MVC actions, take precedence. +[Session](xref:fundamentals/app-state) | Provides support for managing user sessions. | RP/MVC | Before middleware that require Session. +[Static File](xref:fundamentals/static-files) | Provides support for serving static files and directory browsing. | All | Terminal if a request matches a file. +[URL Rewrite](xref:fundamentals/url-rewriting) | Provides support for rewriting URLs and redirecting requests. | All | Before middleware that consume the URL. +[W3C Logging](xref:fundamentals/w3c-logger/index) | Generates server access logs in the [W3C Extended Log File Format](https://www.w3.org/TR/WD-logfile.html). | All | At the beginning of the middleware pipeline. +[Blazor WebAssembly Debugging](xref:blazor/debug) | Debugging Blazor Web Apps that adopt client-side rendering (CSR) inside Chromium developer tools. | BWA | At the beginning of the middleware pipeline. +[WebSockets](xref:fundamentals/websockets) | Enables the WebSockets protocol. | All | Before middleware that are required to accept WebSocket requests. ## Additional resources -* [Lifetime and registration options](xref:fundamentals/dependency-injection#lifetime-and-registration-options) contains a complete sample of middleware with *scoped*, *transient*, and *singleton* lifetime services. +* [Lifetime and registration options (includes middleware sample)](xref:fundamentals/dependency-injection#lifetime-and-registration-options) * * * [Configure gRPC-Web in ASP.NET Core](xref:grpc/browser#configure-grpc-web-in-aspnet-core) @@ -316,7 +1179,3 @@ ASP.NET Core ships with the following middleware components. The *Order* column * * * - -:::moniker-end - -[!INCLUDE[](~/fundamentals/middleware/index/includes/index3-7.md)] diff --git a/aspnetcore/fundamentals/middleware/index/includes/VertGraph.md b/aspnetcore/fundamentals/middleware/index/includes/VertGraph.md deleted file mode 100644 index abc888feefec..000000000000 --- a/aspnetcore/fundamentals/middleware/index/includes/VertGraph.md +++ /dev/null @@ -1,30 +0,0 @@ -```mermaid -graph TD; - subgraph Request-Response - Request((Request)) - Response((Response)) - end - Request--->ExceptionHandler - ExceptionHandler--->HSTS - HSTS--->HttpsRedirection - HttpsRedirection--->StaticFiles - StaticFiles--->Routing - Routing--->CORS - CORS--->Authentication - Authentication--->Authorization - Authorization--->Custom1 - Custom1--->Endpoint - - Endpoint--->Custom1 - Custom1--->Authorization - Authorization--->Authentication - Authentication--->CORS - CORS--->Routing - Routing--->StaticFiles - StaticFiles--->HttpsRedirection - HttpsRedirection--->HSTS - HSTS--->ExceptionHandler - ExceptionHandler--->Response - - -``` diff --git a/aspnetcore/fundamentals/middleware/index/includes/index3-7.md b/aspnetcore/fundamentals/middleware/index/includes/index3-7.md deleted file mode 100644 index 186939ac04aa..000000000000 --- a/aspnetcore/fundamentals/middleware/index/includes/index3-7.md +++ /dev/null @@ -1,829 +0,0 @@ -:::moniker range="= aspnetcore-7.0" - -By [Rick Anderson](https://twitter.com/RickAndMSFT) and [Steve Smith](https://ardalis.com/) - -Middleware is software that's assembled into an app pipeline to handle requests and responses. Each component: - -* Chooses whether to pass the request to the next component in the pipeline. -* Can perform work before and after the next component in the pipeline. - -Request delegates are used to build the request pipeline. The request delegates handle each HTTP request. - -Request delegates are configured using , , and extension methods. An individual request delegate can be specified in-line as an anonymous method (called in-line middleware), or it can be defined in a reusable class. These reusable classes and in-line anonymous methods are *middleware*, also called *middleware components*. Each middleware component in the request pipeline is responsible for invoking the next component in the pipeline or short-circuiting the pipeline. When a middleware short-circuits, it's called a *terminal middleware* because it prevents further middleware from processing the request. - - explains the difference between request pipelines in ASP.NET Core and ASP.NET 4.x and provides additional middleware samples. - -## The role of middleware by app type - -Razor Pages, MVC, Blazor Server, and the server-side project of a hosted Blazor WebAssembly solution process browser requests on the server with middleware. The guidance in this article applies to these types of apps. - -Standalone Blazor WebAssembly apps run entirely on the client and don't process requests with a middleware pipeline. The guidance in this article doesn't apply to standalone Blazor WebAssembly apps. - -## Middleware code analysis - -ASP.NET Core includes many compiler platform analyzers that inspect application code for quality. For more information, see - -## Create a middleware pipeline with `WebApplication` - -The ASP.NET Core request pipeline consists of a sequence of request delegates, called one after the other. The following diagram demonstrates the concept. The thread of execution follows the black arrows. - -![Request processing pattern showing a request arriving, processing through three middlewares, and the response leaving the app. Each middleware runs its logic and hands off the request to the next middleware at the next() statement. After the third middleware processes the request, the request passes back through the prior two middlewares in reverse order for additional processing after their next() statements before leaving the app as a response to the client.](~/fundamentals/middleware/index/_static/request-delegate-pipeline.png) - -Each delegate can perform operations before and after the next delegate. Exception-handling delegates should be called early in the pipeline, so they can catch exceptions that occur in later stages of the pipeline. - -The simplest possible ASP.NET Core app sets up a single request delegate that handles all requests. This case doesn't include an actual request pipeline. Instead, a single anonymous function is called in response to every HTTP request. - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Middleware60/Program.cs)] - -Chain multiple request delegates together with . The `next` parameter represents the next delegate in the pipeline. You can short-circuit the pipeline by *not* calling the `next` parameter. You can typically perform actions both before and after the `next` delegate, as the following example demonstrates: - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain60/Program.cs?highlight=4-9)] - -When a delegate doesn't pass a request to the next delegate, it's called *short-circuiting the request pipeline*. Short-circuiting is often desirable because it avoids unnecessary work. For example, [Static File Middleware](xref:fundamentals/static-files) can act as a *terminal middleware* by processing a request for a static file and short-circuiting the rest of the pipeline. Middleware added to the pipeline before the middleware that terminates further processing still processes code after their `next.Invoke` statements. However, see the following warning about attempting to write to a response that has already been sent. - -> [!WARNING] -> Don't call `next.Invoke` after the response has been sent to the client. Changes to after the response has started throw an exception. For example, [setting headers and a status code throw an exception](xref:fundamentals/best-practices#do-not-modify-the-status-code-or-headers-after-the-response-body-has-started). Writing to the response body after calling `next`: -> -> * May cause a protocol violation. For example, writing more than the stated `Content-Length`. -> * May corrupt the body format. For example, writing an HTML footer to a CSS file. -> -> is a useful hint to indicate if headers have been sent or the body has been written to. - - delegates don't receive a `next` parameter. The first `Run` delegate is always terminal and terminates the pipeline. `Run` is a convention. Some middleware components may expose `Run[Middleware]` methods that run at the end of the pipeline: - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain60/Program.cs?highlight=11-14)] -[!INCLUDE[about the series](~/includes/code-comments-loc.md)] - -In the preceding example, the `Run` delegate writes `"Hello from 2nd delegate."` to the response and then terminates the pipeline. If another `Use` or `Run` delegate is added after the `Run` delegate, it's not called. - -### Prefer app.Use overload that requires passing the context to next - - - -The non-allocating [app.Use](xref:Microsoft.AspNetCore.Builder.IApplicationBuilder.Use%2A) extension method: - -* Requires passing the context to `next`. -* Saves two internal per-request allocations that are required when using the other overload. - -For more information, see [this GitHub issue](https://github.com/dotnet/aspnetcore/pull/31784). - - - -## Middleware order - -The following diagram shows the complete request processing pipeline for ASP.NET Core MVC and Razor Pages apps. You can see how, in a typical app, existing middlewares are ordered and where custom middlewares are added. You have full control over how to reorder existing middlewares or inject new custom middlewares as necessary for your scenarios. - -![ASP.NET Core middleware pipeline](~/fundamentals/middleware/index/_static/middleware-pipeline.svg) - -The **Endpoint** middleware in the preceding diagram executes the filter pipeline for the corresponding app type—MVC or Razor Pages. - -The **Routing** middleware in the preceding diagram is shown following **Static Files**. This is the order that the project templates implement by explicitly calling [app.UseRouting](xref:Microsoft.AspNetCore.Builder.EndpointRoutingApplicationBuilderExtensions.UseRouting%2A). If you don't call `app.UseRouting`, the **Routing** middleware runs at the beginning of the pipeline by default. For more information, see [Routing](xref:fundamentals/routing). - -![ASP.NET Core filter pipeline](~/fundamentals/middleware/index/_static/mvc-endpoint.svg) - -The order that middleware components are added in the `Program.cs` file defines the order in which the middleware components are invoked on requests and the reverse order for the response. The order is **critical** for security, performance, and functionality. - -The following highlighted code in `Program.cs` adds security-related middleware components in the typical recommended order: - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Program70All3.cs?highlight=19-44)] - -In the preceding code: - -* Middleware that is not added when creating a new web app with [individual users accounts](xref:security/authentication/identity) is commented out. -* Not every middleware appears in this exact order, but many do. For example: - * `UseCors`, `UseAuthentication`, and `UseAuthorization` must appear in the order shown. - * `UseCors` currently must appear before `UseResponseCaching`. This requirement is explained in [GitHub issue dotnet/aspnetcore #23218](https://github.com/dotnet/aspnetcore/issues/23218). - * `UseRequestLocalization` must appear before any middleware that might check the request culture, for example, `app.UseStaticFiles()`. - * must be called after `UseRouting` when rate limiting endpoint specific APIs are used. For example, if the [`[EnableRateLimiting]`](xref:Microsoft.AspNetCore.RateLimiting.EnableRateLimitingAttribute) attribute is used, `UseRateLimiter` must be called after `UseRouting`. When calling only global limiters, `UseRateLimiter` can be called before `UseRouting`. - -In some scenarios, middleware has different ordering. For example, caching and compression ordering is scenario specific, and there are multiple valid orderings. For example: - -```csharp -app.UseResponseCaching(); -app.UseResponseCompression(); -``` - -With the preceding code, CPU usage could be reduced by caching the compressed response, but you might end up caching multiple representations of a resource using different compression algorithms such as Gzip or Brotli. - -The following ordering combines static files to allow caching compressed static files: - -```csharp -app.UseResponseCaching(); -app.UseResponseCompression(); -app.UseStaticFiles(); -``` - -The following `Program.cs` code adds middleware components for common app scenarios: - -1. Exception/error handling - * When the app runs in the `Development` environment: - * Developer Exception Page Middleware () reports app runtime errors. - * Database Error Page Middleware () reports database runtime errors. - * When the app runs in the `Production` environment: - * Exception Handler Middleware () catches exceptions thrown in the following middlewares. - * HTTP Strict Transport Security Protocol (HSTS) Middleware () adds the `Strict-Transport-Security` header. -1. HTTPS Redirection Middleware () redirects HTTP requests to HTTPS. -1. Static File Middleware () returns static files and short-circuits further request processing. -1. Cookie Policy Middleware () conforms the app to the EU General Data Protection Regulation (GDPR) regulations. -1. Routing Middleware () to route requests. -1. Authentication Middleware () attempts to authenticate the user before they're allowed access to secure resources. -1. Authorization Middleware () authorizes a user to access secure resources. -1. Session Middleware () establishes and maintains session state. If the app uses session state, call Session Middleware after Cookie Policy Middleware and before MVC Middleware. -1. Endpoint Routing Middleware ( with ) to add Razor Pages endpoints to the request pipeline. - -```csharp -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(); -``` - -In the preceding example code, each middleware extension method is exposed on through the namespace. - - is the first middleware component added to the pipeline. Therefore, the Exception Handler Middleware catches any exceptions that occur in later calls. - -Static File Middleware is called early in the pipeline so that it can handle requests and short-circuit without going through the remaining components. The Static File Middleware provides **no** authorization checks. Any files served by Static File Middleware, including those under *wwwroot*, are publicly available. For an approach to secure static files, see . - -If the request isn't handled by the Static File Middleware, it's passed on to the Authentication Middleware (), which performs authentication. Authentication doesn't short-circuit unauthenticated requests. Although Authentication Middleware authenticates requests, authorization (and rejection) occurs only after MVC selects a specific Razor Page or MVC controller and action. - -The following example demonstrates a middleware order where requests for static files are handled by Static File Middleware before Response Compression Middleware. Static files aren't compressed with this middleware order. The Razor Pages responses can be compressed. - -```csharp -// Static files aren't compressed by Static File Middleware. -app.UseStaticFiles(); - -app.UseRouting(); - -app.UseResponseCompression(); - -app.MapRazorPages(); -``` - -For information about Single Page Applications, see the guides for the [React](xref:spa/react) and [Angular](xref:spa/angular) project templates. - -## UseCors and UseStaticFiles order - -The order for calling `UseCors` and `UseStaticFiles` depends on the app. For more information, see [UseCors and UseStaticFiles order](xref:security/cors#uc1) - -### Forwarded Headers Middleware order - -[!INCLUDE[](~/includes/ForwardedHeaders.md)] - -## Branch the middleware pipeline - - extensions are used as a convention for branching the pipeline. `Map` branches the request pipeline based on matches of the given request path. If the request path starts with the given path, the branch is executed. - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain60/ProgramMap.cs)] - -The following table shows the requests and responses from `http://localhost:1234` using the preceding code. - -| Request | 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. | - -When `Map` is used, the matched path segments are removed from `HttpRequest.Path` and appended to `HttpRequest.PathBase` for each request. - -`Map` supports nesting, for example: - -```csharp -app.Map("/level1", level1App => { - level1App.Map("/level2a", level2AApp => { - // "/level1/level2a" processing - }); - level1App.Map("/level2b", level2BApp => { - // "/level1/level2b" processing - }); -}); -``` - -`Map` can also match multiple segments at once: - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain60/ProgramMultiSeg.cs?highlight=4)] - - branches the request pipeline based on the result of the given predicate. Any predicate of type `Func` can be used to map requests to a new branch of the pipeline. In the following example, a predicate is used to detect the presence of a query string variable `branch`: - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain60/ProgramMapWhen.cs?highlight=4)] - -The following table shows the requests and responses from `http://localhost:1234` using the previous code: - -| Request | Response | -| ----------------------------- | ------------------------------ | -| `localhost:1234` | `Hello from non-Map delegate.` | -| `localhost:1234/?branch=main` | `Branch used = main` | - - also branches the request pipeline based on the result of the given predicate. Unlike with `MapWhen`, this branch is rejoined to the main pipeline if it doesn't short-circuit or contain a terminal middleware: - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain60/ProgramUseWhen.cs?highlight=4-5)] - -In the preceding example, a response of `Hello from non-Map delegate.` is written for all requests. If the request includes a query string variable `branch`, its value is logged before the main pipeline is rejoined. - -## Built-in middleware - -ASP.NET Core ships with the following middleware components. The *Order* column provides notes on middleware placement in the request processing pipeline and under what conditions the middleware may terminate request processing. When a middleware short-circuits the request processing pipeline and prevents further downstream middleware from processing a request, it's called a *terminal middleware*. For more information on short-circuiting, see the [Create a middleware pipeline with WebApplication](#create-a-middleware-pipeline-with-webapplication) section. - -| Middleware | Description | Order | -| ---------- | ----------- | ----- | -| [Authentication](xref:security/authentication/identity) | Provides authentication support. | Before `HttpContext.User` is needed. Terminal for OAuth callbacks. | -| [Authorization](xref:Microsoft.AspNetCore.Builder.AuthorizationAppBuilderExtensions.UseAuthorization%2A) | Provides authorization support. | Immediately after the Authentication Middleware. | -| [Cookie Policy](xref:security/gdpr) | Tracks consent from users for storing personal information and enforces minimum standards for cookie fields, such as `secure` and `SameSite`. | Before middleware that issues cookies. Examples: Authentication, Session, MVC (TempData). | -| [CORS](xref:security/cors) | Configures Cross-Origin Resource Sharing. | Before components that use CORS. `UseCors` currently must go before `UseResponseCaching` due to [this bug](https://github.com/dotnet/aspnetcore/issues/23218).| -| [DeveloperExceptionPage](xref:Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware) | Generates a page with error information that is intended for use only in the `Development` environment. | Before components that generate errors. The project templates automatically register this middleware as the first middleware in the pipeline when the environment is `Development`. | -| [Diagnostics](xref:fundamentals/error-handling) | Several separate middlewares that provide a developer exception page, exception handling, status code pages, and the default web page for new apps. | Before components that generate errors. Terminal for exceptions or serving the default web page for new apps. | -| [Forwarded Headers](xref:host-and-deploy/proxy-load-balancer) | Forwards proxied headers onto the current request. | Before components that consume the updated fields. Examples: scheme, host, client IP, method. | -| [Health Check](xref:host-and-deploy/health-checks) | Checks the health of an ASP.NET Core app and its dependencies, such as checking database availability. | Terminal if a request matches a health check endpoint. | -| [Header Propagation](xref:fundamentals/http-requests#header-propagation-middleware) | Propagates HTTP headers from the incoming request to the outgoing HTTP Client requests. | -| [HTTP Logging](xref:fundamentals/http-logging/index) | Logs HTTP Requests and Responses. | At the beginning of the middleware pipeline. | -| [HTTP Method Override](xref:Microsoft.AspNetCore.Builder.HttpMethodOverrideExtensions) | Allows an incoming POST request to override the method. | Before components that consume the updated method. | -| [HTTPS Redirection](xref:security/enforcing-ssl#require-https) | Redirect all HTTP requests to HTTPS. | Before components that consume the URL. | -| [HTTP Strict Transport Security (HSTS)](xref:security/enforcing-ssl#http-strict-transport-security-protocol-hsts) | Security enhancement middleware that adds a special response header. | Before responses are sent and after components that modify requests. Examples: Forwarded Headers, URL Rewriting. | -| [MVC](xref:mvc/overview) | Processes requests with MVC/Razor Pages. | Terminal if a request matches a route. | -| [OWIN](xref:fundamentals/owin) | Interop with OWIN-based apps, servers, and middleware. | Terminal if the OWIN Middleware fully processes the request. | -| [Output Caching](xref:performance/caching/output) | Provides support for caching responses based on configuration. | Before components that require caching. `UseRouting` must come before `UseOutputCaching`. `UseCORS` must come before `UseOutputCaching`.| -| [Response Caching](xref:performance/caching/middleware) | Provides support for caching responses. This requires client participation to work. Use output caching for complete server control. | Before components that require caching. `UseCORS` must come before `UseResponseCaching`. Is typically not beneficial for UI apps such as Razor Pages because browsers generally set request headers that prevent caching. [Output caching](xref:performance/caching/output) benefits UI apps.| -| [Request Decompression](xref:fundamentals/middleware/request-decompression) | Provides support for decompressing requests. | Before components that read the request body. | -| [Response Compression](xref:performance/response-compression) | Provides support for compressing responses. | Before components that require compression. | -| [Request Localization](xref:fundamentals/localization) | Provides localization support. | Before localization sensitive components. Must appear after Routing Middleware when using . | -| [Endpoint Routing](xref:fundamentals/routing) | Defines and constrains request routes. | Terminal for matching routes. | -| [SPA](xref:Microsoft.AspNetCore.Builder.SpaApplicationBuilderExtensions.UseSpa%2A) | Handles all requests from this point in the middleware chain by returning the default page for the Single Page Application (SPA) | Late in the chain, so that other middleware for serving static files, MVC actions, etc., takes precedence.| -| [Session](xref:fundamentals/app-state) | Provides support for managing user sessions. | Before components that require Session. | -| [Static Files](xref:fundamentals/static-files) | Provides support for serving static files and directory browsing. | Terminal if a request matches a file. | -| [URL Rewrite](xref:fundamentals/url-rewriting) | Provides support for rewriting URLs and redirecting requests. | Before components that consume the URL. | -| [W3CLogging](xref:fundamentals/w3c-logger/index) | Generates server access logs in the [W3C Extended Log File Format](https://www.w3.org/TR/WD-logfile.html). | At the beginning of the middleware pipeline. | -| [WebSockets](xref:fundamentals/websockets) | Enables the WebSockets protocol. | Before components that are required to accept WebSocket requests. | - -## Additional resources - -* [Lifetime and registration options](xref:fundamentals/dependency-injection#lifetime-and-registration-options) contains a complete sample of middleware with *scoped*, *transient*, and *singleton* lifetime services. -* -* -* [Configure gRPC-Web in ASP.NET Core](xref:grpc/browser#configure-grpc-web-in-aspnet-core) -* -* -* -* -* - -:::moniker-end - -:::moniker range="= aspnetcore-6.0" - -By [Rick Anderson](https://twitter.com/RickAndMSFT) and [Steve Smith](https://ardalis.com/) - -Middleware is software that's assembled into an app pipeline to handle requests and responses. Each component: - -* Chooses whether to pass the request to the next component in the pipeline. -* Can perform work before and after the next component in the pipeline. - -Request delegates are used to build the request pipeline. The request delegates handle each HTTP request. - -Request delegates are configured using , , and extension methods. An individual request delegate can be specified in-line as an anonymous method (called in-line middleware), or it can be defined in a reusable class. These reusable classes and in-line anonymous methods are *middleware*, also called *middleware components*. Each middleware component in the request pipeline is responsible for invoking the next component in the pipeline or short-circuiting the pipeline. When a middleware short-circuits, it's called a *terminal middleware* because it prevents further middleware from processing the request. - - explains the difference between request pipelines in ASP.NET Core and ASP.NET 4.x and provides additional middleware samples. - -## Middleware code analysis - -ASP.NET Core includes many compiler platform analyzers that inspect application code for quality. For more information, see - -## Create a middleware pipeline with `WebApplication` - -The ASP.NET Core request pipeline consists of a sequence of request delegates, called one after the other. The following diagram demonstrates the concept. The thread of execution follows the black arrows. - -![Request processing pattern showing a request arriving, processing through three middlewares, and the response leaving the app. Each middleware runs its logic and hands off the request to the next middleware at the next() statement. After the third middleware processes the request, the request passes back through the prior two middlewares in reverse order for additional processing after their next() statements before leaving the app as a response to the client.](~/fundamentals/middleware/index/_static/request-delegate-pipeline.png) - -Each delegate can perform operations before and after the next delegate. Exception-handling delegates should be called early in the pipeline, so they can catch exceptions that occur in later stages of the pipeline. - -The simplest possible ASP.NET Core app sets up a single request delegate that handles all requests. This case doesn't include an actual request pipeline. Instead, a single anonymous function is called in response to every HTTP request. - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Middleware60/Program.cs)] - -Chain multiple request delegates together with . The `next` parameter represents the next delegate in the pipeline. You can short-circuit the pipeline by *not* calling the `next` parameter. You can typically perform actions both before and after the `next` delegate, as the following example demonstrates: - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain60/Program.cs?highlight=4-9)] - -When a delegate doesn't pass a request to the next delegate, it's called *short-circuiting the request pipeline*. Short-circuiting is often desirable because it avoids unnecessary work. For example, [Static File Middleware](xref:fundamentals/static-files) can act as a *terminal middleware* by processing a request for a static file and short-circuiting the rest of the pipeline. Middleware added to the pipeline before the middleware that terminates further processing still processes code after their `next.Invoke` statements. However, see the following warning about attempting to write to a response that has already been sent. - -> [!WARNING] -> Don't call `next.Invoke` after the response has been sent to the client. Changes to after the response has started throw an exception. For example, [setting headers and a status code throw an exception](xref:fundamentals/best-practices#do-not-modify-the-status-code-or-headers-after-the-response-body-has-started). Writing to the response body after calling `next`: -> -> * May cause a protocol violation. For example, writing more than the stated `Content-Length`. -> * May corrupt the body format. For example, writing an HTML footer to a CSS file. -> -> is a useful hint to indicate if headers have been sent or the body has been written to. - - delegates don't receive a `next` parameter. The first `Run` delegate is always terminal and terminates the pipeline. `Run` is a convention. Some middleware components may expose `Run[Middleware]` methods that run at the end of the pipeline: - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain60/Program.cs?highlight=11-14)] -[!INCLUDE[about the series](~/includes/code-comments-loc.md)] - -In the preceding example, the `Run` delegate writes `"Hello from 2nd delegate."` to the response and then terminates the pipeline. If another `Use` or `Run` delegate is added after the `Run` delegate, it's not called. - -### Prefer app.Use overload that requires passing the context to next - - - -The non-allocating [app.Use](xref:Microsoft.AspNetCore.Builder.IApplicationBuilder.Use%2A) extension method: - -* Requires passing the context to `next`. -* Saves two internal per-request allocations that are required when using the other overload. - -For more information, see [this GitHub issue](https://github.com/dotnet/aspnetcore/pull/31784). - - - -## Middleware order - -The following diagram shows the complete request processing pipeline for ASP.NET Core MVC and Razor Pages apps. You can see how, in a typical app, existing middlewares are ordered and where custom middlewares are added. You have full control over how to reorder existing middlewares or inject new custom middlewares as necessary for your scenarios. - -![ASP.NET Core middleware pipeline](~/fundamentals/middleware/index/_static/middleware-pipeline.svg) - -The **Endpoint** middleware in the preceding diagram executes the filter pipeline for the corresponding app type—MVC or Razor Pages. - -The **Routing** middleware in the preceding diagram is shown following **Static Files**. This is the order that the project templates implement by explicitly calling [app.UseRouting](xref:Microsoft.AspNetCore.Builder.EndpointRoutingApplicationBuilderExtensions.UseRouting%2A). If you don't call `app.UseRouting`, the **Routing** middleware runs at the beginning of the pipeline by default. For more information, see [Routing](xref:fundamentals/routing). - -![ASP.NET Core filter pipeline](~/fundamentals/middleware/index/_static/mvc-endpoint.svg) - -The order that middleware components are added in the `Program.cs` file defines the order in which the middleware components are invoked on requests and the reverse order for the response. The order is **critical** for security, performance, and functionality. - -The following highlighted code in `Program.cs` adds security-related middleware components in the typical recommended order: - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Program60All3.cs?highlight=19-43)] - -In the preceding code: - -* Middleware that is not added when creating a new web app with [individual users accounts](xref:security/authentication/identity) is commented out. -* Not every middleware appears in this exact order, but many do. For example: - * `UseCors`, `UseAuthentication`, and `UseAuthorization` must appear in the order shown. - * `UseCors` currently must appear before `UseResponseCaching`. This requirement is explained in [GitHub issue dotnet/aspnetcore #23218](https://github.com/dotnet/aspnetcore/issues/23218). - * `UseRequestLocalization` must appear before any middleware that might check the request culture (for example, `app.UseMvcWithDefaultRoute()`). - -In some scenarios, middleware has different ordering. For example, caching and compression ordering is scenario specific, and there are multiple valid orderings. For example: - -```csharp -app.UseResponseCaching(); -app.UseResponseCompression(); -``` - -With the preceding code, CPU usage could be reduced by caching the compressed response, but you might end up caching multiple representations of a resource using different compression algorithms such as Gzip or Brotli. - -The following ordering combines static files to allow caching compressed static files: - -```csharp -app.UseResponseCaching(); -app.UseResponseCompression(); -app.UseStaticFiles(); -``` - -The following `Program.cs` code adds middleware components for common app scenarios: - -1. Exception/error handling - * When the app runs in the `Development` environment: - * Developer Exception Page Middleware () reports app runtime errors. - * Database Error Page Middleware () reports database runtime errors. - * When the app runs in the `Production` environment: - * Exception Handler Middleware () catches exceptions thrown in the following middlewares. - * HTTP Strict Transport Security Protocol (HSTS) Middleware () adds the `Strict-Transport-Security` header. -1. HTTPS Redirection Middleware () redirects HTTP requests to HTTPS. -1. Static File Middleware () returns static files and short-circuits further request processing. -1. Cookie Policy Middleware () conforms the app to the EU General Data Protection Regulation (GDPR) regulations. -1. Routing Middleware () to route requests. -1. Authentication Middleware () attempts to authenticate the user before they're allowed access to secure resources. -1. Authorization Middleware () authorizes a user to access secure resources. -1. Session Middleware () establishes and maintains session state. If the app uses session state, call Session Middleware after Cookie Policy Middleware and before MVC Middleware. -1. Endpoint Routing Middleware ( with ) to add Razor Pages endpoints to the request pipeline. - -```csharp -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(); -``` - -In the preceding example code, each middleware extension method is exposed on through the namespace. - - is the first middleware component added to the pipeline. Therefore, the Exception Handler Middleware catches any exceptions that occur in later calls. - -Static File Middleware is called early in the pipeline so that it can handle requests and short-circuit without going through the remaining components. The Static File Middleware provides **no** authorization checks. Any files served by Static File Middleware, including those under *wwwroot*, are publicly available. For an approach to secure static files, see . - -If the request isn't handled by the Static File Middleware, it's passed on to the Authentication Middleware (), which performs authentication. Authentication doesn't short-circuit unauthenticated requests. Although Authentication Middleware authenticates requests, authorization (and rejection) occurs only after MVC selects a specific Razor Page or MVC controller and action. - -The following example demonstrates a middleware order where requests for static files are handled by Static File Middleware before Response Compression Middleware. Static files aren't compressed with this middleware order. The Razor Pages responses can be compressed. - -```csharp -// Static files aren't compressed by Static File Middleware. -app.UseStaticFiles(); - -app.UseRouting(); - -app.UseResponseCompression(); - -app.MapRazorPages(); -``` - -For information about Single Page Applications, see the guides for the [React](xref:spa/react) and [Angular](xref:spa/angular) project templates. - -## UseCors and UseStaticFiles order - -The order for calling `UseCors` and `UseStaticFiles` depends on the app. For more information, see [UseCors and UseStaticFiles order](xref:security/cors#uc1) - -### Forwarded Headers Middleware order - -[!INCLUDE[](~/includes/ForwardedHeaders.md)] - -## Branch the middleware pipeline - - extensions are used as a convention for branching the pipeline. `Map` branches the request pipeline based on matches of the given request path. If the request path starts with the given path, the branch is executed. - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain60/ProgramMap.cs)] - -The following table shows the requests and responses from `http://localhost:1234` using the preceding code. - -| Request | 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. | - -When `Map` is used, the matched path segments are removed from `HttpRequest.Path` and appended to `HttpRequest.PathBase` for each request. - -`Map` supports nesting, for example: - -```csharp -app.Map("/level1", level1App => { - level1App.Map("/level2a", level2AApp => { - // "/level1/level2a" processing - }); - level1App.Map("/level2b", level2BApp => { - // "/level1/level2b" processing - }); -}); -``` - -`Map` can also match multiple segments at once: - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain60/ProgramMultiSeg.cs?highlight=4)] - - branches the request pipeline based on the result of the given predicate. Any predicate of type `Func` can be used to map requests to a new branch of the pipeline. In the following example, a predicate is used to detect the presence of a query string variable `branch`: - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain60/ProgramMapWhen.cs?highlight=4)] - -The following table shows the requests and responses from `http://localhost:1234` using the previous code: - -| Request | Response | -| ----------------------------- | ------------------------------ | -| `localhost:1234` | `Hello from non-Map delegate.` | -| `localhost:1234/?branch=main` | `Branch used = main` | - - also branches the request pipeline based on the result of the given predicate. Unlike with `MapWhen`, this branch is rejoined to the main pipeline if it doesn't short-circuit or contain a terminal middleware: - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain60/ProgramUseWhen.cs?highlight=4-5)] - -In the preceding example, a response of `Hello from non-Map delegate.` is written for all requests. If the request includes a query string variable `branch`, its value is logged before the main pipeline is rejoined. - -## Built-in middleware - -ASP.NET Core ships with the following middleware components. The *Order* column provides notes on middleware placement in the request processing pipeline and under what conditions the middleware may terminate request processing. When a middleware short-circuits the request processing pipeline and prevents further downstream middleware from processing a request, it's called a *terminal middleware*. For more information on short-circuiting, see the [Create a middleware pipeline with WebApplication](#create-a-middleware-pipeline-with-webapplication) section. - -| Middleware | Description | Order | -| ---------- | ----------- | ----- | -| [Authentication](xref:security/authentication/identity) | Provides authentication support. | Before `HttpContext.User` is needed. Terminal for OAuth callbacks. | -| [Authorization](xref:Microsoft.AspNetCore.Builder.AuthorizationAppBuilderExtensions.UseAuthorization%2A) | Provides authorization support. | Immediately after the Authentication Middleware. | -| [Cookie Policy](xref:security/gdpr) | Tracks consent from users for storing personal information and enforces minimum standards for cookie fields, such as `secure` and `SameSite`. | Before middleware that issues cookies. Examples: Authentication, Session, MVC (TempData). | -| [CORS](xref:security/cors) | Configures Cross-Origin Resource Sharing. | Before components that use CORS. `UseCors` currently must go before `UseResponseCaching` due to [this bug](https://github.com/dotnet/aspnetcore/issues/23218).| -| [DeveloperExceptionPage](xref:Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware) | Generates a page with error information that is intended for use only in the `Development` environment. | Before components that generate errors. The project templates automatically register this middleware as the first middleware in the pipeline when the environment is `Development`. | -| [Diagnostics](xref:fundamentals/error-handling) | Several separate middlewares that provide a developer exception page, exception handling, status code pages, and the default web page for new apps. | Before components that generate errors. Terminal for exceptions or serving the default web page for new apps. | -| [Forwarded Headers](xref:host-and-deploy/proxy-load-balancer) | Forwards proxied headers onto the current request. | Before components that consume the updated fields. Examples: scheme, host, client IP, method. | -| [Health Check](xref:host-and-deploy/health-checks) | Checks the health of an ASP.NET Core app and its dependencies, such as checking database availability. | Terminal if a request matches a health check endpoint. | -| [Header Propagation](xref:fundamentals/http-requests#header-propagation-middleware) | Propagates HTTP headers from the incoming request to the outgoing HTTP Client requests. | -| [HTTP Logging](xref:fundamentals/http-logging/index) | Logs HTTP Requests and Responses. | At the beginning of the middleware pipeline. | -| [HTTP Method Override](xref:Microsoft.AspNetCore.Builder.HttpMethodOverrideExtensions) | Allows an incoming POST request to override the method. | Before components that consume the updated method. | -| [HTTPS Redirection](xref:security/enforcing-ssl#require-https) | Redirect all HTTP requests to HTTPS. | Before components that consume the URL. | -| [HTTP Strict Transport Security (HSTS)](xref:security/enforcing-ssl#http-strict-transport-security-protocol-hsts) | Security enhancement middleware that adds a special response header. | Before responses are sent and after components that modify requests. Examples: Forwarded Headers, URL Rewriting. | -| [MVC](xref:mvc/overview) | Processes requests with MVC/Razor Pages. | Terminal if a request matches a route. | -| [OWIN](xref:fundamentals/owin) | Interop with OWIN-based apps, servers, and middleware. | Terminal if the OWIN Middleware fully processes the request. | -| [Request Decompression](xref:fundamentals/middleware/request-decompression) | Provides support for decompressing requests. | Before components that read the request body. | -| [Response Caching](xref:performance/caching/middleware) | Provides support for caching responses. | Before components that require caching. `UseCORS` must come before `UseResponseCaching`.| -| [Response Compression](xref:performance/response-compression) | Provides support for compressing responses. | Before components that require compression. | -| [Request Localization](xref:fundamentals/localization) | Provides localization support. | Before localization sensitive components. Must appear after Routing Middleware when using . | -| [Endpoint Routing](xref:fundamentals/routing) | Defines and constrains request routes. | Terminal for matching routes. | -| [SPA](xref:Microsoft.AspNetCore.Builder.SpaApplicationBuilderExtensions.UseSpa%2A) | Handles all requests from this point in the middleware chain by returning the default page for the Single Page Application (SPA) | Late in the chain, so that other middleware for serving static files, MVC actions, etc., takes precedence.| -| [Session](xref:fundamentals/app-state) | Provides support for managing user sessions. | Before components that require Session. | -| [Static Files](xref:fundamentals/static-files) | Provides support for serving static files and directory browsing. | Terminal if a request matches a file. | -| [URL Rewrite](xref:fundamentals/url-rewriting) | Provides support for rewriting URLs and redirecting requests. | Before components that consume the URL. | -| [W3CLogging](xref:fundamentals/w3c-logger/index) | Generates server access logs in the [W3C Extended Log File Format](https://www.w3.org/TR/WD-logfile.html). | At the beginning of the middleware pipeline. | -| [WebSockets](xref:fundamentals/websockets) | Enables the WebSockets protocol. | Before components that are required to accept WebSocket requests. | - -## Additional resources - -* [Lifetime and registration options](xref:fundamentals/dependency-injection#lifetime-and-registration-options) contains a complete sample of middleware with *scoped*, *transient*, and *singleton* lifetime services. -* -* -* [Configure gRPC-Web in ASP.NET Core](xref:grpc/browser#configure-grpc-web-in-aspnet-core) -* -* -* -* -* - -:::moniker-end - -:::moniker range="< aspnetcore-6.0" - -By [Rick Anderson](https://twitter.com/RickAndMSFT) and [Steve Smith](https://ardalis.com/) - -Middleware is software that's assembled into an app pipeline to handle requests and responses. Each component: - -* Chooses whether to pass the request to the next component in the pipeline. -* Can perform work before and after the next component in the pipeline. - -Request delegates are used to build the request pipeline. The request delegates handle each HTTP request. - -Request delegates are configured using , , and extension methods. An individual request delegate can be specified in-line as an anonymous method (called in-line middleware), or it can be defined in a reusable class. These reusable classes and in-line anonymous methods are *middleware*, also called *middleware components*. Each middleware component in the request pipeline is responsible for invoking the next component in the pipeline or short-circuiting the pipeline. When a middleware short-circuits, it's called a *terminal middleware* because it prevents further middleware from processing the request. - - explains the difference between request pipelines in ASP.NET Core and ASP.NET 4.x and provides additional middleware samples. - -## Create a middleware pipeline with IApplicationBuilder - -The ASP.NET Core request pipeline consists of a sequence of request delegates, called one after the other. The following diagram demonstrates the concept. The thread of execution follows the black arrows. - -![Request processing pattern showing a request arriving, processing through three middlewares, and the response leaving the app. Each middleware runs its logic and hands off the request to the next middleware at the next() statement. After the third middleware processes the request, the request passes back through the prior two middlewares in reverse order for additional processing after their next() statements before leaving the app as a response to the client.](~/fundamentals/middleware/index/_static/request-delegate-pipeline.png) - -Each delegate can perform operations before and after the next delegate. Exception-handling delegates should be called early in the pipeline, so they can catch exceptions that occur in later stages of the pipeline. - -The simplest possible ASP.NET Core app sets up a single request delegate that handles all requests. This case doesn't include an actual request pipeline. Instead, a single anonymous function is called in response to every HTTP request. - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Middleware/Startup.cs)] - -Chain multiple request delegates together with . The `next` parameter represents the next delegate in the pipeline. You can short-circuit the pipeline by *not* calling the *next* parameter. You can typically perform actions both before and after the next delegate, as the following example demonstrates: - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain/Startup.cs?highlight=5-10)] - -When a delegate doesn't pass a request to the next delegate, it's called *short-circuiting the request pipeline*. Short-circuiting is often desirable because it avoids unnecessary work. For example, [Static File Middleware](xref:fundamentals/static-files) can act as a *terminal middleware* by processing a request for a static file and short-circuiting the rest of the pipeline. Middleware added to the pipeline before the middleware that terminates further processing still processes code after their `next.Invoke` statements. However, see the following warning about attempting to write to a response that has already been sent. - -> [!WARNING] -> Don't call `next.Invoke` after the response has been sent to the client. Changes to after the response has started throw an exception. For example, [setting headers and a status code throw an exception](xref:fundamentals/best-practices#do-not-modify-the-status-code-or-headers-after-the-response-body-has-started). Writing to the response body after calling `next`: -> -> * May cause a protocol violation. For example, writing more than the stated `Content-Length`. -> * May corrupt the body format. For example, writing an HTML footer to a CSS file. -> -> is a useful hint to indicate if headers have been sent or the body has been written to. - - delegates don't receive a `next` parameter. The first `Run` delegate is always terminal and terminates the pipeline. `Run` is a convention. Some middleware components may expose `Run[Middleware]` methods that run at the end of the pipeline: - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain/Startup.cs?highlight=12-15)] -[!INCLUDE[about the series](~/includes/code-comments-loc.md)] - -In the preceding example, the `Run` delegate writes `"Hello from 2nd delegate."` to the response and then terminates the pipeline. If another `Use` or `Run` delegate is added after the `Run` delegate, it's not called. - - - -## Middleware order - -The following diagram shows the complete request processing pipeline for ASP.NET Core MVC and Razor Pages apps. You can see how, in a typical app, existing middlewares are ordered and where custom middlewares are added. You have full control over how to reorder existing middlewares or inject new custom middlewares as necessary for your scenarios. - -![ASP.NET Core middleware pipeline](~/fundamentals/middleware/index/_static/middleware-pipeline.svg) - -The **Endpoint** middleware in the preceding diagram executes the filter pipeline for the corresponding app type—MVC or Razor Pages. - -![ASP.NET Core filter pipeline](~/fundamentals/middleware/index/_static/mvc-endpoint.svg) - -The order that middleware components are added in the `Startup.Configure` method defines the order in which the middleware components are invoked on requests and the reverse order for the response. The order is **critical** for security, performance, and functionality. - -The following `Startup.Configure` method adds security-related middleware components in the typical recommended order: - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/StartupAll3.cs?name=snippet)] - -In the preceding code: - -* Middleware that is not added when creating a new web app with [individual users accounts](xref:security/authentication/identity) is commented out. -* Not every middleware appears in this exact order, but many do. For example: - * `UseCors`, `UseAuthentication`, and `UseAuthorization` must appear in the order shown. - * `UseCors` currently must appear before `UseResponseCaching` due to [this bug](https://github.com/dotnet/aspnetcore/issues/23218). - * `UseRequestLocalization` must appear before any middleware that might check the request culture (for example, `app.UseMvcWithDefaultRoute()`). - -In some scenarios, middleware has different ordering. For example, caching and compression ordering is scenario specific, and there's multiple valid orderings. For example: - -```csharp -app.UseResponseCaching(); -app.UseResponseCompression(); -``` - -With the preceding code, CPU could be saved by caching the compressed response, but you might end up caching multiple representations of a resource using different compression algorithms such as Gzip or Brotli. - -The following ordering combines static files to allow caching compressed static files: - -```csharp -app.UseResponseCaching(); -app.UseResponseCompression(); -app.UseStaticFiles(); -``` - -The following `Startup.Configure` method adds middleware components for common app scenarios: - -1. Exception/error handling - * When the app runs in the `Development` environment: - * Developer Exception Page Middleware () reports app runtime errors. - * Database Error Page Middleware reports database runtime errors. - * When the app runs in the `Production` environment: - * Exception Handler Middleware () catches exceptions thrown in the following middlewares. - * HTTP Strict Transport Security Protocol (HSTS) Middleware () adds the `Strict-Transport-Security` header. -1. HTTPS Redirection Middleware () redirects HTTP requests to HTTPS. -1. Static File Middleware () returns static files and short-circuits further request processing. -1. Cookie Policy Middleware () conforms the app to the EU General Data Protection Regulation (GDPR) regulations. -1. Routing Middleware () to route requests. -1. Authentication Middleware () attempts to authenticate the user before they're allowed access to secure resources. -1. Authorization Middleware () authorizes a user to access secure resources. -1. Session Middleware () establishes and maintains session state. If the app uses session state, call Session Middleware after Cookie Policy Middleware and before MVC Middleware. -1. Endpoint Routing Middleware ( with ) to add Razor Pages endpoints to the request pipeline. - -```csharp -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(); - }); -} -``` - -In the preceding example code, each middleware extension method is exposed on through the namespace. - - is the first middleware component added to the pipeline. Therefore, the Exception Handler Middleware catches any exceptions that occur in later calls. - -Static File Middleware is called early in the pipeline so that it can handle requests and short-circuit without going through the remaining components. The Static File Middleware provides **no** authorization checks. Any files served by Static File Middleware, including those under *wwwroot*, are publicly available. For an approach to secure static files, see . - -If the request isn't handled by the Static File Middleware, it's passed on to the Authentication Middleware (), which performs authentication. Authentication doesn't short-circuit unauthenticated requests. Although Authentication Middleware authenticates requests, authorization (and rejection) occurs only after MVC selects a specific Razor Page or MVC controller and action. - -The following example demonstrates a middleware order where requests for static files are handled by Static File Middleware before Response Compression Middleware. Static files aren't compressed with this middleware order. The Razor Pages responses can be compressed. - -```csharp -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(); - }); -} -``` - -For Single Page Applications (SPAs), the SPA middleware usually comes last in the middleware pipeline. The SPA middleware comes last: - -* To allow all other middlewares to respond to matching requests first. -* To allow SPAs with client-side routing to run for all routes that are unrecognized by the server app. - -For more details on SPAs, see the guides for the [React](xref:spa/react) and [Angular](xref:spa/angular) project templates. - -### Forwarded Headers Middleware order - -[!INCLUDE[](~/includes/ForwardedHeaders.md)] - -## Branch the middleware pipeline - - extensions are used as a convention for branching the pipeline. `Map` branches the request pipeline based on matches of the given request path. If the request path starts with the given path, the branch is executed. - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain/StartupMap.cs)] - -The following table shows the requests and responses from `http://localhost:1234` using the previous code. - -| Request | 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. | - -When `Map` is used, the matched path segments are removed from `HttpRequest.Path` and appended to `HttpRequest.PathBase` for each request. - -`Map` supports nesting, for example: - -```csharp -app.Map("/level1", level1App => { - level1App.Map("/level2a", level2AApp => { - // "/level1/level2a" processing - }); - level1App.Map("/level2b", level2BApp => { - // "/level1/level2b" processing - }); -}); -``` - -`Map` can also match multiple segments at once: - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain/StartupMultiSeg.cs?highlight=13)] - - branches the request pipeline based on the result of the given predicate. Any predicate of type `Func` can be used to map requests to a new branch of the pipeline. In the following example, a predicate is used to detect the presence of a query string variable `branch`: - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain/StartupMapWhen.cs?highlight=14-15)] - -The following table shows the requests and responses from `http://localhost:1234` using the previous code: - -| Request | Response | -| ----------------------------- | ---------------------------- | -| localhost:1234 | Hello from non-Map delegate. | -| localhost:1234/?branch=main | Branch used = main | - - also branches the request pipeline based on the result of the given predicate. Unlike with `MapWhen`, this branch is rejoined to the main pipeline if it doesn't short-circuit or contain a terminal middleware: - -[!code-csharp[](~/fundamentals/middleware/index/snapshot/Chain/StartupUseWhen.cs?highlight=18-19)] - -In the preceding example, a response of "Hello from main pipeline." is written for all requests. If the request includes a query string variable `branch`, its value is logged before the main pipeline is rejoined. - -## Built-in middleware - -ASP.NET Core ships with the following middleware components. The *Order* column provides notes on middleware placement in the request processing pipeline and under what conditions the middleware may terminate request processing. When a middleware short-circuits the request processing pipeline and prevents further downstream middleware from processing a request, it's called a *terminal middleware*. For more information on short-circuiting, see the [Create a middleware pipeline with IApplicationBuilder](#create-a-middleware-pipeline-with-iapplicationbuilder) section. - -| Middleware | Description | Order | -| ---------- | ----------- | ----- | -| [Antiforgery](xref:security/anti-request-forgery) | Provides anti-request-forgery support. | After authentication and authorization, before endpoints. | -| [Authentication](xref:security/authentication/identity) | Provides authentication support. | Before `HttpContext.User` is needed. Terminal for OAuth callbacks. | -| [Authorization](xref:Microsoft.AspNetCore.Builder.AuthorizationAppBuilderExtensions.UseAuthorization%2A) | Provides authorization support. | Immediately after the Authentication Middleware. | -| [Cookie Policy](xref:security/gdpr) | Tracks consent from users for storing personal information and enforces minimum standards for cookie fields, such as `secure` and `SameSite`. | Before middleware that issues cookies. Examples: Authentication, Session, MVC (TempData). | -| [CORS](xref:security/cors) | Configures Cross-Origin Resource Sharing. | Before components that use CORS. `UseCors` currently must go before `UseResponseCaching` due to [this bug](https://github.com/dotnet/aspnetcore/issues/23218).| -| [Diagnostics](xref:fundamentals/error-handling) | Several separate middlewares that provide a developer exception page, exception handling, status code pages, and the default web page for new apps. | Before components that generate errors. Terminal for exceptions or serving the default web page for new apps. | -| [Forwarded Headers](xref:host-and-deploy/proxy-load-balancer) | Forwards proxied headers onto the current request. | Before components that consume the updated fields. Examples: scheme, host, client IP, method. | -| [Health Check](xref:host-and-deploy/health-checks) | Checks the health of an ASP.NET Core app and its dependencies, such as checking database availability. | Terminal if a request matches a health check endpoint. | -| [Header Propagation](xref:fundamentals/http-requests#header-propagation-middleware) | Propagates HTTP headers from the incoming request to the outgoing HTTP Client requests. | -| [HTTP Method Override](xref:Microsoft.AspNetCore.Builder.HttpMethodOverrideExtensions) | Allows an incoming POST request to override the method. | Before components that consume the updated method. | -| [HTTPS Redirection](xref:security/enforcing-ssl#require-https) | Redirect all HTTP requests to HTTPS. | Before components that consume the URL. | -| [HTTP Strict Transport Security (HSTS)](xref:security/enforcing-ssl#http-strict-transport-security-protocol-hsts) | Security enhancement middleware that adds a special response header. | Before responses are sent and after components that modify requests. Examples: Forwarded Headers, URL Rewriting. | -| [MVC](xref:mvc/overview) | Processes requests with MVC/Razor Pages. | Terminal if a request matches a route. | -| [OWIN](xref:fundamentals/owin) | Interop with OWIN-based apps, servers, and middleware. | Terminal if the OWIN Middleware fully processes the request. | -| [Response Caching](xref:performance/caching/middleware) | Provides support for caching responses. | Before components that require caching. `UseCORS` must come before `UseResponseCaching`.| -| [Response Compression](xref:performance/response-compression) | Provides support for compressing responses. | Before components that require compression. | -| [Request Localization](xref:fundamentals/localization) | Provides localization support. | Before localization sensitive components. Must appear after Routing Middleware when using . | -| [Endpoint Routing](xref:fundamentals/routing) | Defines and constrains request routes. | Terminal for matching routes. | -| [SPA](xref:Microsoft.AspNetCore.Builder.SpaApplicationBuilderExtensions.UseSpa%2A) | Handles all requests from this point in the middleware chain by returning the default page for the Single Page Application (SPA) | Late in the chain, so that other middleware for serving static files, MVC actions, etc., takes precedence.| -| [Session](xref:fundamentals/app-state) | Provides support for managing user sessions. | Before components that require Session. | -| [Static Files](xref:fundamentals/static-files) | Provides support for serving static files and directory browsing. | Terminal if a request matches a file. | -| [URL Rewrite](xref:fundamentals/url-rewriting) | Provides support for rewriting URLs and redirecting requests. | Before components that consume the URL. | -| [WebSockets](xref:fundamentals/websockets) | Enables the WebSocket protocol. | Before components that are required to accept WebSocket requests. | - -## Additional resources - -* [Lifetime and registration options](xref:fundamentals/dependency-injection#lifetime-and-registration-options) contains a complete sample of middleware with *scoped*, *transient*, and *singleton* lifetime services. -* -* -* -* -* -* -* - -:::moniker-end diff --git a/aspnetcore/fundamentals/middleware/index/includes/middleware-pipeline.mermaid-short.md b/aspnetcore/fundamentals/middleware/index/includes/middleware-pipeline.mermaid-short.md deleted file mode 100644 index e7a4bce1181c..000000000000 --- a/aspnetcore/fundamentals/middleware/index/includes/middleware-pipeline.mermaid-short.md +++ /dev/null @@ -1,29 +0,0 @@ -```mermaid -sequenceDiagram - participant Client - participant ASP.NET Core App - participant ExceptionHandler - participant StaticFiles - participant Routing - participant Cors - participant Authentication - participant CustomMiddleware1 - participant Endpoint - - Client->>ASP.NET Core App: Request - ASP.NET Core App->>ExceptionHandler: Request - ExceptionHandler->>StaticFiles: Request - StaticFiles->>Routing: Request - Routing->>Cors: Request - Cors->>Authentication: Request - Authentication->>CustomMiddleware1: Request - CustomMiddleware1->>Endpoint: Request - Endpoint-->>CustomMiddleware1: Response - CustomMiddleware1-->>Authentication: Response - Authentication-->>Cors: Response - Cors-->>Routing: Response - Routing-->>StaticFiles: Response - StaticFiles-->>ExceptionHandler: Response - ExceptionHandler-->>ASP.NET Core App: Response - ASP.NET Core App-->>Client: Response -``` diff --git a/aspnetcore/fundamentals/middleware/index/includes/middleware-pipeline.mermaid-short2.md b/aspnetcore/fundamentals/middleware/index/includes/middleware-pipeline.mermaid-short2.md deleted file mode 100644 index edcb826acd17..000000000000 --- a/aspnetcore/fundamentals/middleware/index/includes/middleware-pipeline.mermaid-short2.md +++ /dev/null @@ -1,22 +0,0 @@ -```mermaid -sequenceDiagram - participant Client - participant ASP.NET Core App - participant StaticFiles - participant Routing - participant Authentication - participant CustomMiddleware1 - participant Endpoint - - Client->>ASP.NET Core App: Request - ASP.NET Core App->>StaticFiles: Request - StaticFiles->>Routing: Request - Routing->>Authentication: Request - Authentication->>CustomMiddleware1: Request - CustomMiddleware1->>Endpoint: Request - Endpoint-->>CustomMiddleware1: Response - CustomMiddleware1-->>Authentication: Response - Authentication-->>Routing: Response - Routing-->>StaticFiles: Response - StaticFiles-->>ASP.NET Core App: Response - ASP.NET Core App-->>Client: Response diff --git a/aspnetcore/fundamentals/middleware/index/includes/middleware-pipeline.mermaid.md b/aspnetcore/fundamentals/middleware/index/includes/middleware-pipeline.mermaid.md deleted file mode 100644 index 5b82555baee6..000000000000 --- a/aspnetcore/fundamentals/middleware/index/includes/middleware-pipeline.mermaid.md +++ /dev/null @@ -1,38 +0,0 @@ -```mermaid -sequenceDiagram - participant Client - participant ASP.NET Core App - participant ExceptionHandler - participant HSTS - participant HttpsRedirection - participant StaticFiles - participant Routing - participant Cors - participant Authentication - participant Authorization - participant CustomMiddleware1 - participant Endpoint - - Client->>ASP.NET Core App: Request - ASP.NET Core App->>ExceptionHandler: Request - ExceptionHandler->>HSTS: Request - HSTS->>HttpsRedirection: Request - HttpsRedirection->>StaticFiles: Request - StaticFiles->>Routing: Request - Routing->>Cors: Request - Cors->>Authentication: Request - Authentication->>Authorization: Request - Authorization->>CustomMiddleware1: Request - CustomMiddleware1->>Endpoint: Request - Endpoint-->>CustomMiddleware1: Response - CustomMiddleware1-->>Authorization: Response - Authorization-->>Authentication: Response - Authentication-->>Cors: Response - Cors-->>Routing: Response - Routing-->>StaticFiles: Response - StaticFiles-->>HttpsRedirection: Response - HttpsRedirection-->>HSTS: Response - HSTS-->>ExceptionHandler: Response - ExceptionHandler-->>ASP.NET Core App: Response - ASP.NET Core App-->>Client: Response -``` \ No newline at end of file diff --git a/aspnetcore/fundamentals/middleware/index/includes/midpipe-request.md b/aspnetcore/fundamentals/middleware/index/includes/midpipe-request.md deleted file mode 100644 index 396cf5fb1368..000000000000 --- a/aspnetcore/fundamentals/middleware/index/includes/midpipe-request.md +++ /dev/null @@ -1,19 +0,0 @@ -```mermaid -graph TD; - subgraph Request Pipeline - A[Exception Handling] --> B; - B[HTTPS Redirection] --> C[Static Files]; - C --> D[Routing]; - D --> E[Authentication]; - E --> F[CORS]; - F --> G[Custom Middleware]; - end; - - subgraph Response Pipeline - G --> F; - F --> E; - E --> D; - D --> C; - C --> B; - B --> A; - end; diff --git a/aspnetcore/fundamentals/middleware/index/includes/shortSequence.md b/aspnetcore/fundamentals/middleware/index/includes/shortSequence.md deleted file mode 100644 index 9365568d39d8..000000000000 --- a/aspnetcore/fundamentals/middleware/index/includes/shortSequence.md +++ /dev/null @@ -1,29 +0,0 @@ -```mermaid -sequenceDiagram - participant Client - participant ASP.NET Core App - participant ExceptionHandler - participant StaticFiles - participant Routing - participant Cors - participant Authentication - participant CustomMiddleware1 - participant Endpoint - - Client->>ASP.NET Core App: Request - ASP.NET Core App->>ExceptionHandler: Request - ExceptionHandler->>StaticFiles: Request - StaticFiles->>Routing: Request - Routing->>Cors: Request - Cors->>Authentication: Request - Authentication->>CustomMiddleware1: Request - CustomMiddleware1->>Endpoint: Request - Endpoint-->>CustomMiddleware1: Response - CustomMiddleware1-->>Authentication: Response - Authentication-->>Cors: Response - Cors-->>Routing: Response - Routing-->>StaticFiles: Response - StaticFiles-->>ExceptionHandler: Response - ExceptionHandler-->>ASP.NET Core App: Response - ASP.NET Core App-->>Client: Response -``` \ No newline at end of file diff --git a/aspnetcore/fundamentals/middleware/index/includes/shorterSequence2.md b/aspnetcore/fundamentals/middleware/index/includes/shorterSequence2.md deleted file mode 100644 index a6a54d1bd2d5..000000000000 --- a/aspnetcore/fundamentals/middleware/index/includes/shorterSequence2.md +++ /dev/null @@ -1,23 +0,0 @@ -```mermaid -sequenceDiagram - participant Client - participant ASP.NET Core App - participant StaticFiles - participant Routing - participant Authentication - participant CustomMiddleware1 - participant Endpoint - - Client->>ASP.NET Core App: Request - ASP.NET Core App->>StaticFiles: Request - StaticFiles->>Routing: Request - Routing->>Authentication: Request - Authentication->>CustomMiddleware1: Request - CustomMiddleware1->>Endpoint: Request - Endpoint-->>CustomMiddleware1: Response - CustomMiddleware1-->>Authentication: Response - Authentication-->>Routing: Response - Routing-->>StaticFiles: Response - StaticFiles-->>ASP.NET Core App: Response - ASP.NET Core App-->>Client: Response -``` \ No newline at end of file diff --git a/aspnetcore/fundamentals/middleware/index/includes/x.md b/aspnetcore/fundamentals/middleware/index/includes/x.md deleted file mode 100644 index d642983c0e71..000000000000 --- a/aspnetcore/fundamentals/middleware/index/includes/x.md +++ /dev/null @@ -1,27 +0,0 @@ -sequenceDiagram - participant Client - participant ASP.NET Core App - participant ExceptionHandler - participant StaticFiles - participant Routing - participant Cors - participant Authentication - participant CustomMiddleware1 - participant Endpoint - - Client->>ASP.NET Core App: Request - ASP.NET Core App->>ExceptionHandler: Request - ExceptionHandler->>StaticFiles: Request - StaticFiles->>Routing: Request - Routing->>Cors: Request - Cors->>Authentication: Request - Authentication->>CustomMiddleware1: Request - CustomMiddleware1->>Endpoint: Request - Endpoint-->>CustomMiddleware1: Response - CustomMiddleware1-->>Authentication: Response - Authentication-->>Cors: Response - Cors-->>Routing: Response - Routing-->>StaticFiles: Response - StaticFiles-->>ExceptionHandler: Response - ExceptionHandler-->>ASP.NET Core App: Response - ASP.NET Core App-->>Client: Response diff --git a/aspnetcore/fundamentals/middleware/index/includes/x.md.svg b/aspnetcore/fundamentals/middleware/index/includes/x.md.svg deleted file mode 100644 index 0965a4da7202..000000000000 --- a/aspnetcore/fundamentals/middleware/index/includes/x.md.svg +++ /dev/null @@ -1,13 +0,0 @@ -Client -ASP.NET Core App -ExceptionHandler -StaticFiles -Routing -Cors -Authentication -CustomMiddleware1 -Endpoint -ClientASP.NET Core AppExceptionHandlerStaticFilesRoutingCorsAuthenticationCustomMiddleware1EndpointRequestRequestRequestRequestRequestRequestRequestRequestResponseResponseResponseResponseResponseResponseResponseResponse \ No newline at end of file diff --git a/aspnetcore/fundamentals/middleware/index/snapshot/Chain/Startup.cs b/aspnetcore/fundamentals/middleware/index/snapshot/Chain/Startup.cs deleted file mode 100644 index 7daa89a4db4c..000000000000 --- a/aspnetcore/fundamentals/middleware/index/snapshot/Chain/Startup.cs +++ /dev/null @@ -1,17 +0,0 @@ -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."); - }); - } -} diff --git a/aspnetcore/fundamentals/middleware/index/snapshot/Chain/StartupMap.cs b/aspnetcore/fundamentals/middleware/index/snapshot/Chain/StartupMap.cs deleted file mode 100644 index 57cab9e3eb73..000000000000 --- a/aspnetcore/fundamentals/middleware/index/snapshot/Chain/StartupMap.cs +++ /dev/null @@ -1,30 +0,0 @@ -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."); - }); - } -} diff --git a/aspnetcore/fundamentals/middleware/index/snapshot/Chain/StartupMapWhen.cs b/aspnetcore/fundamentals/middleware/index/snapshot/Chain/StartupMapWhen.cs deleted file mode 100644 index f6e9b276177f..000000000000 --- a/aspnetcore/fundamentals/middleware/index/snapshot/Chain/StartupMapWhen.cs +++ /dev/null @@ -1,22 +0,0 @@ -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."); - }); - } -} diff --git a/aspnetcore/fundamentals/middleware/index/snapshot/Chain/StartupMultiSeg.cs b/aspnetcore/fundamentals/middleware/index/snapshot/Chain/StartupMultiSeg.cs deleted file mode 100644 index 0587d1d4537f..000000000000 --- a/aspnetcore/fundamentals/middleware/index/snapshot/Chain/StartupMultiSeg.cs +++ /dev/null @@ -1,20 +0,0 @@ -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."); - }); - } -} diff --git a/aspnetcore/fundamentals/middleware/index/snapshot/Chain/StartupUseWhen.cs b/aspnetcore/fundamentals/middleware/index/snapshot/Chain/StartupUseWhen.cs deleted file mode 100644 index 6366f79414f5..000000000000 --- a/aspnetcore/fundamentals/middleware/index/snapshot/Chain/StartupUseWhen.cs +++ /dev/null @@ -1,26 +0,0 @@ -public class Startup -{ - private void HandleBranchAndRejoin(IApplicationBuilder app, ILogger 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 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."); - }); - } -} diff --git a/aspnetcore/fundamentals/middleware/index/snapshot/Chain60/Program.cs b/aspnetcore/fundamentals/middleware/index/snapshot/Chain60/Program.cs deleted file mode 100644 index 068f924af16a..000000000000 --- a/aspnetcore/fundamentals/middleware/index/snapshot/Chain60/Program.cs +++ /dev/null @@ -1,16 +0,0 @@ -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(); diff --git a/aspnetcore/fundamentals/middleware/index/snapshot/Chain60/ProgramMap.cs b/aspnetcore/fundamentals/middleware/index/snapshot/Chain60/ProgramMap.cs deleted file mode 100644 index e478e8a53f08..000000000000 --- a/aspnetcore/fundamentals/middleware/index/snapshot/Chain60/ProgramMap.cs +++ /dev/null @@ -1,29 +0,0 @@ -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"); - }); -} \ No newline at end of file diff --git a/aspnetcore/fundamentals/middleware/index/snapshot/Chain60/ProgramMapWhen.cs b/aspnetcore/fundamentals/middleware/index/snapshot/Chain60/ProgramMapWhen.cs deleted file mode 100644 index ba98e16e2f03..000000000000 --- a/aspnetcore/fundamentals/middleware/index/snapshot/Chain60/ProgramMapWhen.cs +++ /dev/null @@ -1,20 +0,0 @@ -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}"); - }); -} \ No newline at end of file diff --git a/aspnetcore/fundamentals/middleware/index/snapshot/Chain60/ProgramMultiSeg.cs b/aspnetcore/fundamentals/middleware/index/snapshot/Chain60/ProgramMultiSeg.cs deleted file mode 100644 index 4f3c1f1ba44e..000000000000 --- a/aspnetcore/fundamentals/middleware/index/snapshot/Chain60/ProgramMultiSeg.cs +++ /dev/null @@ -1,19 +0,0 @@ -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"); - }); -} diff --git a/aspnetcore/fundamentals/middleware/index/snapshot/Chain60/ProgramUseWhen.cs b/aspnetcore/fundamentals/middleware/index/snapshot/Chain60/ProgramUseWhen.cs deleted file mode 100644 index a15237e0f48f..000000000000 --- a/aspnetcore/fundamentals/middleware/index/snapshot/Chain60/ProgramUseWhen.cs +++ /dev/null @@ -1,27 +0,0 @@ -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>(); - - 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. - }); -} \ No newline at end of file diff --git a/aspnetcore/fundamentals/middleware/index/snapshot/Middleware/Startup.cs b/aspnetcore/fundamentals/middleware/index/snapshot/Middleware/Startup.cs deleted file mode 100644 index d93aab1c5353..000000000000 --- a/aspnetcore/fundamentals/middleware/index/snapshot/Middleware/Startup.cs +++ /dev/null @@ -1,10 +0,0 @@ -public class Startup -{ - public void Configure(IApplicationBuilder app) - { - app.Run(async context => - { - await context.Response.WriteAsync("Hello, World!"); - }); - } -} diff --git a/aspnetcore/fundamentals/middleware/index/snapshot/Middleware60/Program.cs b/aspnetcore/fundamentals/middleware/index/snapshot/Middleware60/Program.cs deleted file mode 100644 index a13ee4df070c..000000000000 --- a/aspnetcore/fundamentals/middleware/index/snapshot/Middleware60/Program.cs +++ /dev/null @@ -1,9 +0,0 @@ -var builder = WebApplication.CreateBuilder(args); -var app = builder.Build(); - -app.Run(async context => -{ - await context.Response.WriteAsync("Hello world!"); -}); - -app.Run(); \ No newline at end of file diff --git a/aspnetcore/fundamentals/middleware/index/snapshot/Program60All3.cs b/aspnetcore/fundamentals/middleware/index/snapshot/Program60All3.cs deleted file mode 100644 index 02b1cb378927..000000000000 --- a/aspnetcore/fundamentals/middleware/index/snapshot/Program60All3.cs +++ /dev/null @@ -1,50 +0,0 @@ -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(options => - options.UseSqlServer(connectionString)); -builder.Services.AddDatabaseDeveloperPageExceptionFilter(); - -builder.Services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) - .AddEntityFrameworkStores(); -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(); diff --git a/aspnetcore/fundamentals/middleware/index/snapshot/Program60UseExtensions.cs b/aspnetcore/fundamentals/middleware/index/snapshot/Program60UseExtensions.cs deleted file mode 100644 index 315a7f4cc5e9..000000000000 --- a/aspnetcore/fundamentals/middleware/index/snapshot/Program60UseExtensions.cs +++ /dev/null @@ -1,19 +0,0 @@ -var builder = WebApplication.CreateBuilder(args); -var app = builder.Build(); - -/* - 1. next is type of RequestDelegate which requires passing the HttpContext - 2. Use this for performance benefits - 3. Saves two per request allocations over the previous Use extension -*/ - -#region snippet1 -app.Use(async (context, next) => -{ - // Do work that doesn't write to the Response. - await next.Invoke(context); - // Do logging or other work that doesn't write to the Response. -}); -#endregion - -app.Run(); diff --git a/aspnetcore/fundamentals/middleware/index/snapshot/Program70All3.cs b/aspnetcore/fundamentals/middleware/index/snapshot/Program70All3.cs deleted file mode 100644 index 5dcfcc7e033e..000000000000 --- a/aspnetcore/fundamentals/middleware/index/snapshot/Program70All3.cs +++ /dev/null @@ -1,48 +0,0 @@ -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(options => - options.UseSqlServer(connectionString)); -builder.Services.AddDatabaseDeveloperPageExceptionFilter(); - -builder.Services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) - .AddEntityFrameworkStores(); -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(); diff --git a/aspnetcore/fundamentals/middleware/index/snapshot/StartupAll3.cs b/aspnetcore/fundamentals/middleware/index/snapshot/StartupAll3.cs deleted file mode 100644 index 43e9260575ca..000000000000 --- a/aspnetcore/fundamentals/middleware/index/snapshot/StartupAll3.cs +++ /dev/null @@ -1,69 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Identity; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using WebApplication51.Data; - -namespace WebApplication51 -{ - public class Startup - { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - public void ConfigureServices(IServiceCollection services) - { - services.AddDbContext(options => - options.UseSqlServer( - Configuration.GetConnectionString("DefaultConnection"))); - services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) - .AddEntityFrameworkStores(); - services.AddRazorPages(); - } - - #region snippet - 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?}"); - }); - } - #endregion - } -} diff --git a/aspnetcore/fundamentals/middleware/rate-limit/samples/readmd.md b/aspnetcore/fundamentals/middleware/rate-limit/samples/readmd.md deleted file mode 100644 index 87e5a8686e0a..000000000000 --- a/aspnetcore/fundamentals/middleware/rate-limit/samples/readmd.md +++ /dev/null @@ -1 +0,0 @@ -Delete this file after adding rate limiting sample code. diff --git a/aspnetcore/fundamentals/middleware/request-response.md b/aspnetcore/fundamentals/middleware/request-response.md index 975eff2e17d8..c6c47a45512b 100644 --- a/aspnetcore/fundamentals/middleware/request-response.md +++ b/aspnetcore/fundamentals/middleware/request-response.md @@ -43,8 +43,6 @@ Suppose the goal is to create a middleware that reads the entire request body as [!code-csharp[](request-response/samples/3.x/RequestResponseSample/Startup.cs?name=GetListOfStringsFromStream)] -[!INCLUDE[about the series](~/includes/code-comments-loc.md)] - This code works, but there are some issues: * Before appending to the `StringBuilder`, the example creates another string (`encodedString`) that is thrown away immediately. This process occurs for all bytes in the stream, so the result is extra memory allocation the size of the entire request body. diff --git a/aspnetcore/fundamentals/routing/includes/routing3-7.md b/aspnetcore/fundamentals/routing/includes/routing3-7.md index 5cbb1a201253..f509cd6f7929 100644 --- a/aspnetcore/fundamentals/routing/includes/routing3-7.md +++ b/aspnetcore/fundamentals/routing/includes/routing3-7.md @@ -2103,8 +2103,6 @@ The following example shows routing with [health checks](xref:host-and-deploy/he :::code language="csharp" source="~/fundamentals/routing/samples/3.x/RoutingSample/AuthorizationStartup.cs" id="snippet"::: -[!INCLUDE[request localized comments](~/includes/code-comments-loc.md)] - The preceding example demonstrates how: * The authorization middleware can be used with routing. diff --git a/aspnetcore/grpc/aspnetcore.md b/aspnetcore/grpc/aspnetcore.md index c7a57280335e..2d7f42f9fca9 100644 --- a/aspnetcore/grpc/aspnetcore.md +++ b/aspnetcore/grpc/aspnetcore.md @@ -52,7 +52,6 @@ In `Program.cs`: * Each gRPC service is added to the routing pipeline through the `MapGrpcService` method. [!code-csharp[](~/tutorials/grpc/grpc-start/sample/sample6/GrpcGreeter/Program.cs?highlight=9,14)] -[!INCLUDE[about the series](~/includes/code-comments-loc.md)] ASP.NET Core middleware and features share the routing pipeline, therefore an app can be configured to serve additional request handlers. The additional request handlers, such as MVC controllers, work in parallel with the configured gRPC services. diff --git a/aspnetcore/grpc/aspnetcore/includes/aspnetcore3.md b/aspnetcore/grpc/aspnetcore/includes/aspnetcore3.md index 3add546da0f5..af559c584412 100644 --- a/aspnetcore/grpc/aspnetcore/includes/aspnetcore3.md +++ b/aspnetcore/grpc/aspnetcore/includes/aspnetcore3.md @@ -43,7 +43,6 @@ In `Startup.cs`: * Each gRPC service is added to the routing pipeline through the `MapGrpcService` method. [!code-csharp[](~/tutorials/grpc/grpc-start/sample/sample3-5/GrpcGreeter/Startup.cs?name=snippet&highlight=7,24)] -[!INCLUDE[about the series](~/includes/code-comments-loc.md)] ASP.NET Core middleware and features share the routing pipeline, therefore an app can be configured to serve additional request handlers. The additional request handlers, such as MVC controllers, work in parallel with the configured gRPC services. diff --git a/aspnetcore/grpc/aspnetcore/includes/aspnetcore3_1.md b/aspnetcore/grpc/aspnetcore/includes/aspnetcore3_1.md index 8f28feacf61c..c70f0e4e06c4 100644 --- a/aspnetcore/grpc/aspnetcore/includes/aspnetcore3_1.md +++ b/aspnetcore/grpc/aspnetcore/includes/aspnetcore3_1.md @@ -43,7 +43,6 @@ In `Startup.cs`: * Each gRPC service is added to the routing pipeline through the `MapGrpcService` method. [!code-csharp[](~/tutorials/grpc/grpc-start/sample/sample3-5/GrpcGreeter/Startup.cs?name=snippet&highlight=7,24)] -[!INCLUDE[about the series](~/includes/code-comments-loc.md)] ASP.NET Core middleware and features share the routing pipeline, therefore an app can be configured to serve additional request handlers. The additional request handlers, such as MVC controllers, work in parallel with the configured gRPC services. diff --git a/aspnetcore/grpc/aspnetcore/includes/aspnetcore5.md b/aspnetcore/grpc/aspnetcore/includes/aspnetcore5.md index b71f6874baa4..3248c68dda26 100644 --- a/aspnetcore/grpc/aspnetcore/includes/aspnetcore5.md +++ b/aspnetcore/grpc/aspnetcore/includes/aspnetcore5.md @@ -43,7 +43,6 @@ In `Startup.cs`: * Each gRPC service is added to the routing pipeline through the `MapGrpcService` method. [!code-csharp[](~/tutorials/grpc/grpc-start/sample/sample3-5/GrpcGreeter/Startup.cs?name=snippet&highlight=7,24)] -[!INCLUDE[about the series](~/includes/code-comments-loc.md)] ASP.NET Core middleware and features share the routing pipeline, therefore an app can be configured to serve additional request handlers. The additional request handlers, such as MVC controllers, work in parallel with the configured gRPC services. diff --git a/aspnetcore/grpc/aspnetcore/includes/aspnetcore6.md b/aspnetcore/grpc/aspnetcore/includes/aspnetcore6.md index cb9ac776838a..fa3e4b73d0e7 100644 --- a/aspnetcore/grpc/aspnetcore/includes/aspnetcore6.md +++ b/aspnetcore/grpc/aspnetcore/includes/aspnetcore6.md @@ -43,7 +43,6 @@ In `Program.cs`: * Each gRPC service is added to the routing pipeline through the `MapGrpcService` method. [!code-csharp[](~/tutorials/grpc/grpc-start/sample/sample6/GrpcGreeter/Program.cs?highlight=9,14)] -[!INCLUDE[about the series](~/includes/code-comments-loc.md)] ASP.NET Core middleware and features share the routing pipeline, therefore an app can be configured to serve additional request handlers. The additional request handlers, such as MVC controllers, work in parallel with the configured gRPC services. diff --git a/aspnetcore/grpc/aspnetcore/includes/aspnetcore7.md b/aspnetcore/grpc/aspnetcore/includes/aspnetcore7.md index 2fc276a7492c..3413d7b1a989 100644 --- a/aspnetcore/grpc/aspnetcore/includes/aspnetcore7.md +++ b/aspnetcore/grpc/aspnetcore/includes/aspnetcore7.md @@ -43,7 +43,6 @@ In `Program.cs`: * Each gRPC service is added to the routing pipeline through the `MapGrpcService` method. [!code-csharp[](~/tutorials/grpc/grpc-start/sample/sample6/GrpcGreeter/Program.cs?highlight=9,14)] -[!INCLUDE[about the series](~/includes/code-comments-loc.md)] ASP.NET Core middleware and features share the routing pipeline, therefore an app can be configured to serve additional request handlers. The additional request handlers, such as MVC controllers, work in parallel with the configured gRPC services. diff --git a/aspnetcore/grpc/basics.md b/aspnetcore/grpc/basics.md index b2ac423c1840..34d85ff7ae86 100644 --- a/aspnetcore/grpc/basics.md +++ b/aspnetcore/grpc/basics.md @@ -30,7 +30,6 @@ For example, consider the *greet.proto* file used in [Get started with gRPC serv * `SayHello` sends a `HelloRequest` message and receives a `HelloReply` message: [!code-protobuf[](~/tutorials/grpc/grpc-start/sample/sample6/GrpcGreeter/Protos/greet.proto)] -[!INCLUDE[about the series](~/includes/code-comments-loc.md)] ## Add a `.proto` file to a C\# app @@ -106,7 +105,6 @@ For example, consider the *greet.proto* file used in [Get started with gRPC serv * `SayHello` sends a `HelloRequest` message and receives a `HelloReply` message: [!code-protobuf[](~/tutorials/grpc/grpc-start/sample/sample3-5/GrpcGreeter/Protos/greet.proto)] -[!INCLUDE[about the series](~/includes/code-comments-loc.md)] ## Add a `.proto` file to a C\# app diff --git a/aspnetcore/host-and-deploy/linux-nginx.md b/aspnetcore/host-and-deploy/linux-nginx.md index 235ce1d02275..1150942a84fb 100644 --- a/aspnetcore/host-and-deploy/linux-nginx.md +++ b/aspnetcore/host-and-deploy/linux-nginx.md @@ -106,7 +106,7 @@ For the purposes of this guide, a single instance of Nginx is used. It runs on t Because requests are forwarded by reverse proxy, use the [Forwarded Headers Middleware](xref:host-and-deploy/proxy-load-balancer) from the [`Microsoft.AspNetCore.HttpOverrides`](https://www.nuget.org/packages/Microsoft.AspNetCore.HttpOverrides) package, which is automatically included in ASP.NET Core apps via the [shared framework's `Microsoft.AspNetCore.App` metapackage](xref:fundamentals/metapackage-app). The middleware updates the `Request.Scheme`, using the `X-Forwarded-Proto` header, so that redirect URIs and other security policies work correctly. -[!INCLUDE[](~/includes/ForwardedHeaders.md)] +Forwarded Headers Middleware should run before other middleware. This ordering ensures that the middleware relying on forwarded headers information can consume the header values for processing. To run Forwarded Headers Middleware after Diagnostics and Error Handling Middleware, see [Forwarded Headers Middleware order](xref:host-and-deploy/proxy-load-balancer#forwarded-headers-middleware-order). Invoke the method before calling other middleware. Configure the middleware to forward the `X-Forwarded-For` and `X-Forwarded-Proto` headers: diff --git a/aspnetcore/host-and-deploy/linux-nginx/includes/linux-nginx5.md b/aspnetcore/host-and-deploy/linux-nginx/includes/linux-nginx5.md index 06ebd2efa333..94cdecc2ab1e 100644 --- a/aspnetcore/host-and-deploy/linux-nginx/includes/linux-nginx5.md +++ b/aspnetcore/host-and-deploy/linux-nginx/includes/linux-nginx5.md @@ -79,7 +79,7 @@ For the purposes of this guide, a single instance of Nginx is used. It runs on t Because requests are forwarded by reverse proxy, use the [Forwarded Headers Middleware](xref:host-and-deploy/proxy-load-balancer) from the [`Microsoft.AspNetCore.HttpOverrides`](https://www.nuget.org/packages/Microsoft.AspNetCore.HttpOverrides) package. The middleware updates the `Request.Scheme`, using the `X-Forwarded-Proto` header, so that redirect URIs and other security policies work correctly. -[!INCLUDE[](~/includes/ForwardedHeaders.md)] +Forwarded Headers Middleware should run before other middleware. This ordering ensures that the middleware relying on forwarded headers information can consume the header values for processing. To run Forwarded Headers Middleware after Diagnostics and Error Handling Middleware, see [Forwarded Headers Middleware order](xref:host-and-deploy/proxy-load-balancer#forwarded-headers-middleware-order). Invoke the method at the top of `Program.cs` before calling other middleware. Configure the middleware to forward the `X-Forwarded-For` and `X-Forwarded-Proto` headers: @@ -522,9 +522,9 @@ For the purposes of this guide, a single instance of Nginx is used. It runs on t Because requests are forwarded by reverse proxy, use the [Forwarded Headers Middleware](xref:host-and-deploy/proxy-load-balancer) from the [`Microsoft.AspNetCore.HttpOverrides`](https://www.nuget.org/packages/Microsoft.AspNetCore.HttpOverrides) package. The middleware updates the `Request.Scheme`, using the `X-Forwarded-Proto` header, so that redirect URIs and other security policies work correctly. -[!INCLUDE[](~/includes/ForwardedHeaders.md)] +Forwarded Headers Middleware should run before other middleware. This ordering ensures that the middleware relying on forwarded headers information can consume the header values for processing. To run Forwarded Headers Middleware after Diagnostics and Error Handling Middleware, see [Forwarded Headers Middleware order](xref:host-and-deploy/proxy-load-balancer#forwarded-headers-middleware-order). -Invoke the method at the top of `Startup.Configure` before calling other middleware. Configure the middleware to forward the `X-Forwarded-For` and `X-Forwarded-Proto` headers: +Invoke the method at the top of the request processing pipeline before calling other middleware. Configure the middleware to forward the `X-Forwarded-For` and `X-Forwarded-Proto` headers: ```csharp using Microsoft.AspNetCore.HttpOverrides; diff --git a/aspnetcore/host-and-deploy/proxy-load-balancer.md b/aspnetcore/host-and-deploy/proxy-load-balancer.md index 18831d273c80..8e130b00fe4e 100644 --- a/aspnetcore/host-and-deploy/proxy-load-balancer.md +++ b/aspnetcore/host-and-deploy/proxy-load-balancer.md @@ -66,8 +66,6 @@ Outside of using [IIS Integration](xref:host-and-deploy/iis/index#enable-the-iis Configure the middleware with to forward the [`X-Forwarded-For`](https://developer.mozilla.org/docs/Web/HTTP/Headers/X-Forwarded-For) and [`X-Forwarded-Proto`](https://developer.mozilla.org/docs/Web/HTTP/Headers/X-Forwarded-Proto) headers. - - ### Forwarded Headers Middleware order [Forwarded Headers Middleware](https://github.com/dotnet/aspnetcore/blob/main/src/Middleware/HttpOverrides/src/ForwardedHeadersOptions.cs) should run before other middleware. This ordering ensures that the middleware relying on forwarded headers information can consume the header values for processing. Forwarded Headers Middleware can run after diagnostics and error handling, but it must be run before calling : @@ -139,7 +137,7 @@ app.UseRouting(); ``` > [!NOTE] -> When using (see ), [`app.UseRouting`](xref:Microsoft.AspNetCore.Builder.EndpointRoutingApplicationBuilderExtensions.UseRouting%2A) must be called after `UsePathBase` so that the routing middleware can observe the modified path before matching routes. Otherwise, routes are matched before the path is rewritten by `UsePathBase` as described in the [Middleware Ordering](xref:fundamentals/middleware/index#order) and [Routing](xref:fundamentals/routing) articles. +> When using (see ), [`app.UseRouting`](xref:Microsoft.AspNetCore.Builder.EndpointRoutingApplicationBuilderExtensions.UseRouting%2A) must be called after `UsePathBase` so that the routing middleware can observe the modified path before matching routes. Otherwise, routes are matched before the path is rewritten by `UsePathBase` as described in and . The original path and path base are reapplied when the middleware is called again in reverse. For more information on middleware order processing, see . diff --git a/aspnetcore/includes/ForwardedHeaders.md b/aspnetcore/includes/ForwardedHeaders.md deleted file mode 100644 index b95a02685f87..000000000000 --- a/aspnetcore/includes/ForwardedHeaders.md +++ /dev/null @@ -1 +0,0 @@ -Forwarded Headers Middleware should run before other middleware. This ordering ensures that the middleware relying on forwarded headers information can consume the header values for processing. To run Forwarded Headers Middleware after diagnostics and error handling middleware, see [Forwarded Headers Middleware order](xref:host-and-deploy/proxy-load-balancer#fhmo). \ No newline at end of file diff --git a/aspnetcore/includes/code-comments-loc.md b/aspnetcore/includes/code-comments-loc.md deleted file mode 100644 index f65eeb64275e..000000000000 --- a/aspnetcore/includes/code-comments-loc.md +++ /dev/null @@ -1 +0,0 @@ -If you would like to see code comments translated to languages other than English, let us know in [this GitHub discussion issue](https://github.com/MicrosoftDocs/feedback/issues/2515). \ No newline at end of file diff --git a/aspnetcore/mvc/advanced/custom-model-binding.md b/aspnetcore/mvc/advanced/custom-model-binding.md index 092b9e44b9a7..fe3de3cf6ec6 100644 --- a/aspnetcore/mvc/advanced/custom-model-binding.md +++ b/aspnetcore/mvc/advanced/custom-model-binding.md @@ -58,7 +58,6 @@ When creating your own custom model binder, you can implement your own `IModelBi The following example shows how to use `ByteArrayModelBinder` to convert a base64-encoded string to a `byte[]` and save the result to a file: [!code-csharp[](custom-model-binding/samples/3.x/CustomModelBindingSample/Controllers/ImageController.cs?name=snippet_Post)] -[!INCLUDE[about the series](~/includes/code-comments-loc.md)] You can POST a base64-encoded string to the previous api method using a tool like [curl](https://curl.haxx.se/). diff --git a/aspnetcore/mvc/controllers/filters.md b/aspnetcore/mvc/controllers/filters.md index 42b8163db2fd..e5e14a1783b4 100644 --- a/aspnetcore/mvc/controllers/filters.md +++ b/aspnetcore/mvc/controllers/filters.md @@ -34,6 +34,10 @@ Filters run within the *ASP.NET Core action invocation pipeline*, sometimes refe :::image source="~/mvc/controllers/filters/_static/filter-pipeline-1.png" alt-text="The request is processed through Other Middleware, Routing Middleware, Action Selection, and the Action Invocation Pipeline. The request processing continues back through Action Selection, Routing Middleware, and various Other Middleware before becoming a response sent to the client."::: +The following diagram shows the filter pipeline execution order for MVC and Razor Pages: + +![ASP.NET Core filter pipeline](~/mvc/controllers/filters/_static/filter-pipeline-3.svg) + ### Filter types Each filter type is executed at a different stage in the filter pipeline: diff --git a/aspnetcore/fundamentals/middleware/index/_static/mvc-endpoint.svg b/aspnetcore/mvc/controllers/filters/_static/filter-pipeline-3.svg similarity index 100% rename from aspnetcore/fundamentals/middleware/index/_static/mvc-endpoint.svg rename to aspnetcore/mvc/controllers/filters/_static/filter-pipeline-3.svg diff --git a/aspnetcore/performance/response-compression.md b/aspnetcore/performance/response-compression.md index ef25f73e95a8..347a2022d8fd 100644 --- a/aspnetcore/performance/response-compression.md +++ b/aspnetcore/performance/response-compression.md @@ -18,8 +18,7 @@ Network bandwidth is a limited resource. Reducing the size of the response usual ## Compression with HTTPS -Compressed responses over secure connections can be controlled with the option, which is disabled by default because of the security risk. Using compression with dynamically generated pages can expose the app to [CRIME](https://wikipedia.org/wiki/CRIME_(security_exploit)) and [BREACH](https://wikipedia.org/wiki/BREACH_(security_exploit)) attacks. CRIME and BREACH attacks can be - mitigated in ASP.NET Core with antiforgery tokens. For more information, see . For information on mitigating BREACH attacks, see [mitigations](http://www.breachattack.com/#mitigations) at http://www.breachattack.com/ +Compressed responses over secure connections can be controlled with the option, which is disabled by default because of the security risk. Using compression with dynamically generated pages can expose the app to [CRIME](https://wikipedia.org/wiki/CRIME_(security_exploit)) and [BREACH](https://wikipedia.org/wiki/BREACH_(security_exploit)) attacks. CRIME and BREACH attacks can be mitigated in ASP.NET Core with antiforgery tokens. For more information, see . For information on mitigating BREACH attacks, see [mitigations](http://www.breachattack.com/#mitigations) at http://www.breachattack.com/ Even when `EnableForHttps` is disabled in the app, IIS, IIS Express, and [Azure App Service](xref:host-and-deploy/azure-iis-errors-reference) can apply gzip at the IIS web server. When reviewing response headers, take note of the [Server](https://developer.mozilla.org/docs/Web/HTTP/Headers/Server) value. An unexpected `content-encoding` response header value may be the result of the web server and not the ASP.NET Core app configuration. diff --git a/aspnetcore/security/authentication/cookie.md b/aspnetcore/security/authentication/cookie.md index 909083f8677c..435924dd7770 100644 --- a/aspnetcore/security/authentication/cookie.md +++ b/aspnetcore/security/authentication/cookie.md @@ -73,8 +73,6 @@ Create a with any required is only used on a few specific paths by default, for example, the login path and logout paths. For more information see the [CookieAuthenticationHandler source](https://github.com/dotnet/aspnetcore/blob/f2e6e6ff334176540ef0b3291122e359c2106d1a/src/Security/Authentication/Cookies/src/CookieAuthenticationHandler.cs#L334). @@ -243,8 +241,6 @@ Create a with any required is only used on a few specific paths by default, for example, the login path and logout paths. For more information see the [CookieAuthenticationHandler source](https://github.com/dotnet/aspnetcore/blob/f2e6e6ff334176540ef0b3291122e359c2106d1a/src/Security/Authentication/Cookies/src/CookieAuthenticationHandler.cs#L334). diff --git a/aspnetcore/security/data-protection/implementation/key-management.md b/aspnetcore/security/data-protection/implementation/key-management.md index c399296bac5b..6a4e09ad30f0 100644 --- a/aspnetcore/security/data-protection/implementation/key-management.md +++ b/aspnetcore/security/data-protection/implementation/key-management.md @@ -70,8 +70,6 @@ The sample below demonstrates using the `IKeyManager` interface to inspect and m [!code-csharp[](key-management/samples/key-management.cs)] -[!INCLUDE[about the series](~/includes/code-comments-loc.md)] - ## Key storage The data protection system has a heuristic whereby it attempts to deduce an appropriate key storage location and encryption-at-rest mechanism automatically. The key persistence mechanism is also configurable by the app developer. The following documents discuss the in-box implementations of these mechanisms: diff --git a/aspnetcore/security/data-protection/implementation/key-storage-providers.md b/aspnetcore/security/data-protection/implementation/key-storage-providers.md index 29cf2b52abc1..e29a90cd0d54 100644 --- a/aspnetcore/security/data-protection/implementation/key-storage-providers.md +++ b/aspnetcore/security/data-protection/implementation/key-storage-providers.md @@ -316,8 +316,6 @@ To configure the EF Core provider, call the and implement : [!code-csharp[Main](key-storage-providers/sample/MyKeysContext.cs)] diff --git a/aspnetcore/signalr/authn-and-authz.md b/aspnetcore/signalr/authn-and-authz.md index e54523729aef..e219c1f5decd 100644 --- a/aspnetcore/signalr/authn-and-authz.md +++ b/aspnetcore/signalr/authn-and-authz.md @@ -276,8 +276,6 @@ On the server, bearer token authentication is configured using the [JWT Bearer m [!code-csharp[Configure Server to accept access token from Query String](authn-and-authz/sample/Startup.cs?name=snippet)] -[!INCLUDE[request localized comments](~/includes/code-comments-loc.md)] - > [!NOTE] > The query string is used on browsers when connecting with WebSockets and Server-Sent Events due to browser API limitations. When using HTTPS, query string values are secured by the TLS connection. However, many servers log query string values. For more information, see [Security considerations in ASP.NET Core SignalR](xref:signalr/security). SignalR uses headers to transmit tokens in environments which support them (such as the .NET and Java clients).