diff --git a/aspnetcore/fundamentals/minimal-apis/includes/middleware8.md b/aspnetcore/fundamentals/minimal-apis/includes/middleware8.md index e4fac5ce2335..56c7869a1fc2 100644 --- a/aspnetcore/fundamentals/minimal-apis/includes/middleware8.md +++ b/aspnetcore/fundamentals/minimal-apis/includes/middleware8.md @@ -1,11 +1,17 @@ :::moniker range=">= aspnetcore-8.0" -[`WebApplication`](xref:fundamentals/minimal-apis/webapplication) automatically adds the following middleware in [Minimal API applications](xref:fundamentals/apis) depending on certain conditions: -* [`UseDeveloperExceptionPage`](/dotnet/api/microsoft.aspnetcore.diagnostics.developerexceptionpagemiddleware) is added first when the [`HostingEnvironment`](xref:fundamentals/environments) is `"Development"`. -* [`UseRouting`](/dotnet/api/microsoft.aspnetcore.builder.endpointroutingapplicationbuilderextensions.userouting) is added second if user code didn't already call `UseRouting` and if there are endpoints configured, for example `app.MapGet`. -* [`UseEndpoints`](/dotnet/api/microsoft.aspnetcore.builder.endpointroutingapplicationbuilderextensions.useendpoints) is added at the end of the middleware pipeline if any endpoints are configured. -* [`UseAuthentication`](/dotnet/api/microsoft.aspnetcore.builder.authappbuilderextensions.useauthentication) is added immediately after `UseRouting` if user code didn't already call `UseAuthentication` and if [`IAuthenticationSchemeProvider`](/dotnet/api/microsoft.aspnetcore.authentication.iauthenticationschemeprovider) can be detected in the service provider. `IAuthenticationSchemeProvider` is added by default when using [`AddAuthentication`](/dotnet/api/microsoft.extensions.dependencyinjection.authenticationservicecollectionextensions.addauthentication), and services are detected using [`IServiceProviderIsService`](/dotnet/api/microsoft.extensions.dependencyinjection.iserviceproviderisservice). -* [`UseAuthorization`](/dotnet/api/microsoft.aspnetcore.builder.authorizationappbuilderextensions.useauthorization) is added next if user code didn't already call `UseAuthorization` and if [`IAuthorizationHandlerProvider`](/dotnet/api/microsoft.aspnetcore.authorization.iauthorizationhandlerprovider) can be detected in the service provider. `IAuthorizationHandlerProvider` is added by default when using [`AddAuthorization`](/dotnet/api/microsoft.extensions.dependencyinjection.authenticationservicecollectionextensions.addauthentication), and services are detected using `IServiceProviderIsService`. +[WebApplication](xref:fundamentals/minimal-apis/webapplication) automatically adds the following middleware in [Minimal API applications](xref:fundamentals/apis) depending on certain conditions: + +* [UseDeveloperExceptionPage](/dotnet/api/microsoft.aspnetcore.diagnostics.developerexceptionpagemiddleware) is added first when the [HostingEnvironment](xref:fundamentals/environments) is `"Development"`. + +* [UseRouting](/dotnet/api/microsoft.aspnetcore.builder.endpointroutingapplicationbuilderextensions.userouting) is added second, if the user code didn't already call `UseRouting` and endpoints are configured, for example `app.MapGet`. + +* [UseEndpoints](/dotnet/api/microsoft.aspnetcore.builder.endpointroutingapplicationbuilderextensions.useendpoints) is added at the end of the middleware pipeline if endpoints are configured. + +* [UseAuthentication](/dotnet/api/microsoft.aspnetcore.builder.authappbuilderextensions.useauthentication) is added immediately after `UseRouting`, if user code didn't already call `UseAuthentication` and if [IAuthenticationSchemeProvider](/dotnet/api/microsoft.aspnetcore.authentication.iauthenticationschemeprovider) can be detected in the service provider. `IAuthenticationSchemeProvider` is added by default when you use [AddAuthentication](/dotnet/api/microsoft.extensions.dependencyinjection.authenticationservicecollectionextensions.addauthentication), and services are detected by using [IServiceProviderIsService](/dotnet/api/microsoft.extensions.dependencyinjection.iserviceproviderisservice). + +* [UseAuthorization](/dotnet/api/microsoft.aspnetcore.builder.authorizationappbuilderextensions.useauthorization) is added next, if user code didn't already call `UseAuthorization` and if [IAuthorizationHandlerProvider](/dotnet/api/microsoft.aspnetcore.authorization.iauthorizationhandlerprovider) can be detected in the service provider. `IAuthorizationHandlerProvider` is added by default when you use [AddAuthorization](/dotnet/api/microsoft.extensions.dependencyinjection.authenticationservicecollectionextensions.addauthentication), and services are detected by using `IServiceProviderIsService`. + * User configured middleware and endpoints are added between `UseRouting` and `UseEndpoints`. The following code is effectively what the automatic middleware being added to the app produces: @@ -28,10 +34,10 @@ if (isAuthorizationConfigured) app.UseAuthorization(); } -// user middleware/endpoints +// User middleware/endpoints app.CustomMiddleware(...); app.MapGet("/", () => "hello world"); -// end user middleware/endpoints +// End user middleware/endpoints app.UseEndpoints(e => {}); ``` @@ -44,7 +50,7 @@ app.UseAuthentication(); app.UseAuthorization(); ``` -If middleware should be run before route matching occurs, should be called and the middleware should be placed before the call to `UseRouting`. isn't required in this case as it is automatically added as described previously: +If middleware should run before route matching occurs, should be called and the middleware should be placed before the call to `UseRouting`. isn't required in this case because it's automatically added as described earlier: ```csharp app.Use((context, next) => @@ -54,13 +60,15 @@ app.Use((context, next) => app.UseRouting(); -// other middleware and endpoints +// Other middleware and endpoints ``` When adding a terminal middleware: * The middleware must be added after `UseEndpoints`. -* The app needs to call `UseRouting` and `UseEndpoints` so that the terminal middleware can be placed at the correct location. + +* The app needs to call `UseRouting` and `UseEndpoints` so the terminal middleware can be placed at the correct location. + ```csharp app.UseRouting(); @@ -77,6 +85,6 @@ app.Run(context => Terminal middleware is middleware that runs if no endpoint handles the request. -For information on antiforgery middleware in Minimal APIs, see +For information on antiforgery middleware in Minimal APIs, see . :::moniker-end diff --git a/aspnetcore/fundamentals/minimal-apis/includes/route-handlers.md b/aspnetcore/fundamentals/minimal-apis/includes/route-handlers.md index 559a06f0e67a..da51ca4a0932 100644 --- a/aspnetcore/fundamentals/minimal-apis/includes/route-handlers.md +++ b/aspnetcore/fundamentals/minimal-apis/includes/route-handlers.md @@ -1,4 +1,6 @@ -Route handlers are methods that execute when the route matches. Route handlers can be a lambda expression, a local function, an instance method or a static method. Route handlers can be synchronous or asynchronous. +Route handlers are methods that execute when the route matches. Route handlers can be a lambda expression, a local function, an instance method, or a static method. Route handlers can be synchronous or asynchronous. + +The following sections provide examples of different route handlers. ### Lambda expression @@ -16,58 +18,61 @@ Route handlers are methods that execute when the route matches. Route handlers c [!code-csharp[](~/fundamentals/minimal-apis/7.0-samples/WebMinAPIs/Program.cs?name=snippet_sm)] -### Endpoint defined outside of `Program.cs` +### Endpoint defined outside of Program.cs -Minimal APIs don't have to be located in `Program.cs`. +Minimal APIs don't have to be located in the _Program.cs_ file. For example, you can set up the structure in the _Program.cs_ file, and define the endpoint in a separate file: -`Program.cs` +**Program.cs** [!code-csharp[](~/fundamentals/minimal-apis/8.0-samples/MinAPISeparateFile/Program.cs)] -`TodoEndpoints.cs` +**TodoEndpoints.cs** [!code-csharp[](~/fundamentals/minimal-apis/8.0-samples/MinAPISeparateFile/TodoEndpoints.cs)] -See also [Route groups](#route-groups) later in this article. +For more information, see the [Route groups](#route-groups) section later in this article. ### Named endpoints and link generation -Endpoints can be given names in order to generate URLs to the endpoint. Using a named endpoint avoids having to hard code paths in an app: +You can supply a name for your endpoints to generate URLs that target the endpoint. Using a named endpoint avoids having to hard code paths in an app: [!code-csharp[](~/fundamentals/minimal-apis/samples/WebMinAPIs/Program.cs?name=snippet_nr)] -The preceding code displays `The link to the hello route is /hello` from the `/` endpoint. +The preceding code displays the message _`The link to the hello route is /hello`_ from the `/` (forward slash) endpoint. -**NOTE**: Endpoint names are case sensitive. +#### Criteria for endpoint names -Endpoint names: +Endpoint names must satisfy the following criteria: -* Must be globally unique. -* Are used as the OpenAPI operation id when OpenAPI support is enabled. For more information, see [OpenAPI](xref:fundamentals/openapi/aspnetcore-openapi). +- Endpoint names are case sensitive. +* Endpoint names must be globally unique. +* Endpoint names are used as the OpenAPI operation identifier (ID) when OpenAPI support is enabled. For more information, see [Generate OpenAPI documents](xref:fundamentals/openapi/aspnetcore-openapi). -### Route Parameters +### Route parameters Route parameters can be captured as part of the route pattern definition: [!code-csharp[](~/fundamentals/minimal-apis/7.0-samples/WebMinAPIs/Program.cs?name=snippet_rp)] -The preceding code returns `The user id is 3 and book id is 7` from the URI `/users/3/books/7`. +The preceding code returns the message _The user id is 3 and book id is 7_ from the URI `/users/3/books/7`. -The route handler can declare the parameters to capture. When a request is made to a route with parameters declared to capture, the parameters are parsed and passed to the handler. This makes it easy to capture the values in a type safe way. In the preceding code, `userId` and `bookId` are both `int`. +The route handler can declare the parameters to capture. When a request is made to a route with parameters declared to capture, the parameters are parsed and passed to the handler. This approach makes it easy to capture the values in a type-safe way. In the preceding code, the `userId` and `bookId` parameters are both type `int`. -In the preceding code, if either route value cannot be converted to an `int`, an exception is thrown. The GET request `/users/hello/books/3` throws the following exception: +In the preceding code, if either route value can't be converted to an `int`, the command throws an exception. The GET request `/users/hello/books/3` throws the following exception: -**`BadHttpRequestException: Failed to bind parameter "int userId" from "hello".`** +```output +BadHttpRequestException: Failed to bind parameter "int userId" from "hello". +``` ### Wildcard and catch all routes -The following catch all route returns `Routing to hello` from the `/posts/hello' endpoint: +The following catch all route returns _Routing to hello_ from the `/posts/hello` endpoint: [!code-csharp[](~/fundamentals/minimal-apis/7.0-samples/WebMinAPIs/Program.cs?name=snippet_wild)] ### Route constraints -Route constraints constrain the matching behavior of a route. +Route constraints restrict the matching behavior of a route. ```csharp var builder = WebApplication.CreateBuilder(args); @@ -82,13 +87,13 @@ app.Run(); The following table demonstrates the preceding route templates and their behavior: -| Route Template | Example Matching URI | -|--|--| +| Route template | Example matching URI | +|---|---| | `/todos/{id:int}` | `/todos/1` | | `/todos/{text}` | `/todos/something` | | `/posts/{slug:regex(^[a-z0-9_-]+$)}` | `/posts/mypost` | -For more information, see [Route constraint reference](xref:fundamentals/routing) in . +For more information, see [Route constraint reference](xref:fundamentals/routing#route-constraints) in . ### Route groups diff --git a/aspnetcore/fundamentals/minimal-apis/middleware.md b/aspnetcore/fundamentals/minimal-apis/middleware.md index a9ba02681de9..d4dcd606576f 100644 --- a/aspnetcore/fundamentals/minimal-apis/middleware.md +++ b/aspnetcore/fundamentals/minimal-apis/middleware.md @@ -1,20 +1,28 @@ --- title: Middleware with Minimal API applications author: BrennanConroy -description: Use middleware in Minimal API applications +description: Use middleware in Minimal API applications, including automatic middleware, user-configured middleware, and terminal middleware. ms.author: wpickett -ms.date: 02/16/2024 +ms.date: 04/28/2026 monikerRange: '>= aspnetcore-7.0' uid: fundamentals/minimal-apis/middleware + +# customer intent: As an ASP.NET developer, I want to use middleware in ASP.NET Code, so I can use the functionality to handle requests and responses in my Minimal API apps. --- # Middleware in Minimal API apps [!INCLUDE[](~/includes/not-latest-version.md)] +This article describes how to use middleware in Minimal API applications. Take advantage of automatic middleware in your Minimal API apps, or define user-configured middleware and terminal middleware. + +## Available middleware + [!INCLUDE [webapplication7](~/fundamentals/minimal-apis/includes/middleware7.md)] [!INCLUDE [webapplication8](~/fundamentals/minimal-apis/includes/middleware8.md)] -For more information about middleware see [ASP.NET Core Middleware](xref:fundamentals/middleware/index), and the [list of built-in middleware](xref:fundamentals/middleware/index#built-in-middleware) that can be added to applications. +## Related content -For more information about Minimal APIs see [APIs overview](xref:fundamentals/apis). +- [ASP.NET Core Middleware](xref:fundamentals/middleware/index) +- [Built-in middleware (list)](xref:fundamentals/middleware/index#built-in-middleware) +- [Minimal APIs overview](xref:fundamentals/apis) \ No newline at end of file diff --git a/aspnetcore/fundamentals/minimal-apis/min-api-filters.md b/aspnetcore/fundamentals/minimal-apis/min-api-filters.md index 84214f13eef4..2b7708ace548 100644 --- a/aspnetcore/fundamentals/minimal-apis/min-api-filters.md +++ b/aspnetcore/fundamentals/minimal-apis/min-api-filters.md @@ -1,11 +1,13 @@ --- title: Filters in Minimal API apps author: wadepickett -description: Use filters in Minimal API apps +description: Use filters in Minimal API apps, including validation of an object with a filter, and registering a filter. ms.author: wpickett -ms.date: 8/11/2022 +ms.date: 04/28/2026 monikerRange: '>= aspnetcore-7.0' uid: fundamentals/minimal-apis/min-api-filters + +# customer intent: As an ASP.NET developer, I want to use filters in Minimal APIs, so I can validate and log request and reponse data for my apps. --- # Filters in Minimal API apps @@ -14,33 +16,37 @@ uid: fundamentals/minimal-apis/min-api-filters By [Fiyaz Bin Hasan](https://github.com/fiyazbinhasan), [Martin Costello](https://twitter.com/martin_costello), and [Rick Anderson](https://twitter.com/RickAndMSFT) -Minimal API filters allow developers to implement business logic that supports: +Minimal API filters allow developers to implement business logic that supports the following tasks: + +* Run code before and after the endpoint handler +* Inspect and modify parameters provided during an endpoint handler invocation +* Intercept the response behavior of an endpoint handler + +Filters are helpful in many scenarios: -* Running code before and after the endpoint handler. -* Inspecting and modifying parameters provided during an endpoint handler invocation. -* Intercepting the response behavior of an endpoint handler. +* Validate request parameters and body sent to an endpoint +* Log information about the request and response +* Validate a request targets a supported API version -Filters can be helpful in the following scenarios: +This article describes how to use filters in your Minimal API apps, such as for validating request data sent to your app and logging the response. -* Validating the request parameters and body that are sent to an endpoint. -* Logging information about the request and response. -* Validating that a request is targeting a supported API version. +## Work with filters -Filters can be registered by providing a [Delegate](/dotnet/csharp/programming-guide/delegates/) that takes a [`EndpointFilterInvocationContext`](https://github.com/dotnet/aspnetcore/blob/main/src/Http/Http.Abstractions/src/EndpointFilterInvocationContext.cs) and returns a [`EndpointFilterDelegate`](https://github.com/dotnet/aspnetcore/blob/main/src/Http/Http.Abstractions/src/EndpointFilterDelegate.cs). The `EndpointFilterInvocationContext` provides access to the `HttpContext` of the request and an `Arguments` list indicating the arguments passed to the handler in the order in which they appear in the declaration of the handler. +Filters are registered by providing a [Delegate](/dotnet/csharp/programming-guide/delegates/) that takes a [EndpointFilterInvocationContext](https://github.com/dotnet/aspnetcore/blob/main/src/Http/Http.Abstractions/src/EndpointFilterInvocationContext.cs) and returns a [EndpointFilterDelegate](https://github.com/dotnet/aspnetcore/blob/main/src/Http/Http.Abstractions/src/EndpointFilterDelegate.cs). The `EndpointFilterInvocationContext` provides access to the `HttpContext` of the request and an `Arguments` list. The list specifies the arguments passed to the handler in the order in which they appear in the declaration of the handler. [!code-csharp[](~/fundamentals/minimal-apis/min-api-filters/7samples/Filters/Program.cs?name=snippet1)] The preceding code: * Calls the `AddEndpointFilter` extension method to add a filter to the `/colorSelector/{color}` endpoint. -* Returns the color specified except for the value `"Red"`. +* Returns the color specified, except for the value `"Red"`. * Returns [Results.Problem](xref:Microsoft.AspNetCore.Http.Results.Problem%2A) when the `/colorSelector/Red` is requested. -* Uses `next` as the `EndpointFilterDelegate` and `invocationContext` as the `EndpointFilterInvocationContext` to invoke the next filter in the pipeline or the request delegate if the last filter has been invoked. +* Uses `next` as the `EndpointFilterDelegate` and `invocationContext` as the `EndpointFilterInvocationContext` to invoke the next filter in the pipeline, or the request delegate if the last filter is already invoked. -The filter is run before the endpoint handler. When multiple `AddEndpointFilter` invocations are made on a handler: +The filter runs before the endpoint handler. When multiple `AddEndpointFilter` invocations are made on a handler: -* Filter code called before the `EndpointFilterDelegate` (`next`) is called are executed in order of First In, First Out (FIFO) order. -* Filter code called after the `EndpointFilterDelegate` (`next`) is called are executed in order of First In, Last Out (FILO) order. +* The execution order of filter code called _before_ the call to `EndpointFilterDelegate` (`next`) is First In, First Out (FIFO). +* The execution order of filter code called _after_ the call to `EndpointFilterDelegate` (`next`) is First In, Last Out (FILO). [!code-csharp[](~/fundamentals/minimal-apis/min-api-filters/7samples/Filters/Program.cs?name=snippet_xyz)] @@ -60,7 +66,7 @@ The following code uses filters that implement the `IEndpointFilter` interface: [!code-csharp[](~/fundamentals/minimal-apis/min-api-filters/7samples/Filters/Program.cs?name=snippet_abc)] -In the preceding code, the filters and handlers logs show the order they are run: +In the preceding code, the logs for the filters and handlers show the run order: ```dotnetcli AEndpointFilter Before next @@ -72,7 +78,7 @@ BEndpointFilter After next AEndpointFilter After next ``` -Filters implementing the `IEndpointFilter` interface are shown in the following example: +Filters that implement the `IEndpointFilter` interface are shown in the following example: [!code-csharp[](~/fundamentals/minimal-apis/min-api-filters/7samples/Filters/EndpointFilters/AbcEndpointFilters.cs)] @@ -85,13 +91,13 @@ Consider a filter that validates a `Todo` object: In the preceding code: * The `EndpointFilterInvocationContext` object provides access to the parameters associated with a particular request issued to the endpoint via the `GetArguments` method. -* The filter is registered using a `delegate` that takes a `EndpointFilterInvocationContext` and returns a `EndpointFilterDelegate`. +* The filter is registered by using a `delegate` that takes a `EndpointFilterInvocationContext` and returns a `EndpointFilterDelegate`. -In addition to being passed as delegates, filters can be registered by implementing the `IEndpointFilter` interface. The following code shows the preceding filter encapsulated in a class which implements `IEndpointFilter`: +In addition to being passed as delegates, filters can be registered by implementing the `IEndpointFilter` interface. The following code shows the preceding filter encapsulated in a class that implements `IEndpointFilter`: [!code-csharp[](~/fundamentals/minimal-apis/min-api-filters/7samples/todo/EndpointFilters/ToDoIsValidFilter.cs?name=snippet)] -Filters that implement the `IEndpointFilter` interface can resolve dependencies from [Dependency Injection(DI)](xref:fundamentals/dependency-injection), as shown in the previous code. Although filters can resolve dependencies from DI, filters themselves can ***not*** be resolved from DI. +Filters that implement the `IEndpointFilter` interface can resolve dependencies from [Dependency Injection (DI)](xref:fundamentals/dependency-injection), as shown in the previous code. Although filters can resolve dependencies from DI, filters themselves **can't** be resolved from DI. The `ToDoIsValidFilter` is applied to the following endpoints: @@ -101,27 +107,27 @@ The following filter validates the `Todo` object and modifies the `Name` propert [!code-csharp[](~/fundamentals/minimal-apis/min-api-filters/7samples/todo/EndpointFilters/ToDoIsValidFilter.cs?name=snippet2&highlight=7)] -## Register a filter using an endpoint filter factory +## Register a filter by using an endpoint filter factory -In some scenarios, it might be necessary to cache some of the information provided in the [`MethodInfo`](/dotnet/api/system.reflection.methodinfo) in a filter. For example, let's assume that we wanted to verify that the handler an endpoint filter is attached to has a first parameter that evaluates to a `Todo` type. +In some scenarios, it might be necessary to cache some of the information provided in the [MethodInfo](/dotnet/api/system.reflection.methodinfo) in a filter. Suppose you want to verify that the handler attached to an endpoint filter has a first parameter that evaluates to a `Todo` type. [!code-csharp[](~/fundamentals/minimal-apis/min-api-filters/7samples/todo/Program.cs?name=snippet_filterfactory1)] In the preceding code: -* The `EndpointFilterFactoryContext` object provides access to the [`MethodInfo`](/dotnet/api/system.reflection.methodinfo) associated with the endpoint's handler. +* The `EndpointFilterFactoryContext` object provides access to the [MethodInfo](/dotnet/api/system.reflection.methodinfo) associated with the endpoint's handler. * The signature of the handler is examined by inspecting `MethodInfo` for the expected type signature. If the expected signature is found, the validation filter is registered onto the endpoint. This factory pattern is useful to register a filter that depends on the signature of the target endpoint handler. -* If a matching signature isn't found, then a pass-through filter is registered. +* If a matching signature isn't found, a pass-through filter is registered. ## Register a filter on controller actions -In some scenarios, it might be necessary to apply the same filter logic for both route-handler based endpoints and controller actions. For this scenario, it is possible to invoke `AddEndpointFilter` on `ControllerActionEndpointConventionBuilder` to support executing the same filter logic on actions and endpoints. +In some scenarios, it might be necessary to apply the same filter logic for both route-handler based endpoints and controller actions. For this scenario, you can invoke `AddEndpointFilter` on `ControllerActionEndpointConventionBuilder` to support executing the same filter logic on actions and endpoints. [!code-csharp[](~/fundamentals/minimal-apis/min-api-filters/7samples/Filters/Program.cs?name=snippet_action_endpoint_filters)] -## Additional Resources +## Related content -* [View or download sample code](https://github.com/aspnet/Docs/tree/main/aspnetcore/fundamentals/minimal-apis/min-api-filters/7samples) ([how to download](xref:fundamentals/index#how-to-download-a-sample)) -* [ValidationFilterRouteHandlerBuilderExtensions](https://github.com/DamianEdwards/MinimalApis.Extensions/blob/main/src/MinimalApis.Extensions/Filters/ValidationFilterRouteHandlerBuilderExtensions.cs) Validation extension methods. -* -* +* [View or download sample code](https://github.com/aspnet/Docs/tree/main/aspnetcore/fundamentals/minimal-apis/min-api-filters/7samples) ([How to download](xref:fundamentals/index#how-to-download-a-sample)) +* [ValidationFilterRouteHandlerBuilderExtensions (Validation extension methods)](https://github.com/DamianEdwards/MinimalApis.Extensions/blob/main/src/MinimalApis.Extensions/Filters/ValidationFilterRouteHandlerBuilderExtensions.cs) +* [Tutorial: Create a Minimal API with ASP.NET Core](xref:tutorials/min-web-api) +* [Authentication and authorization in Minimal APIs](xref:fundamentals/minimal-apis/security) \ No newline at end of file diff --git a/aspnetcore/fundamentals/minimal-apis/route-handlers.md b/aspnetcore/fundamentals/minimal-apis/route-handlers.md index bf33e64e501d..4aa6d779b20d 100644 --- a/aspnetcore/fundamentals/minimal-apis/route-handlers.md +++ b/aspnetcore/fundamentals/minimal-apis/route-handlers.md @@ -1,31 +1,41 @@ --- title: Route handlers in Minimal API apps author: wadepickett -description: Learn how to handle requests in Minimal API apps. +description: Learn how to handle route requests in Minimal API apps, define preferred methods, bind route parameters, and process the request response. ms.author: wpickett monikerRange: '>= aspnetcore-7.0' -ms.date: 10/31/2022 +ms.date: 04/28/2026 uid: fundamentals/minimal-apis/route-handlers + +# customer intent: As an ASP.NET developer, I want to use route handlers in Minimal APIs, so I can define my preferred methods to execute when a route matches. --- -# Route Handlers in Minimal API apps +# Route handlers in Minimal API apps [!INCLUDE[](~/includes/not-latest-version.md)] -A configured `WebApplication` supports `Map{Verb}` and where `{Verb}` is a Pascal-cased HTTP method like `Get`, `Post`, `Put` or `Delete`: +A configured `WebApplication` supports `Map{Verb}` and the , where `{Verb}` is a Pascal-cased HTTP method like `Get`, `Post`, `Put`, or `Delete`: [!code-csharp[](7.0-samples/WebMinAPIs/Program.cs?name=snippet_r1)] -The arguments passed to these methods are called "route handlers". +The arguments passed to these methods are called _route handlers_. + +This article describes how to use route handlers, including examples, parameters, route groups, and route constraints. -## Route handlers +## Work with route handlers [!INCLUDE [route handling](includes/route-handlers.md)] -## Parameter binding +## Bind parameters in a route handler describes the rules in detail for how route handler parameters are populated. -## Responses +## Handle the response from the route handler describes in detail how values returned from route handlers are converted into responses. + +## Related content + +- [Routing in ASP.NET Core](xref:fundamentals/routing) +- [Parameter Binding in Minimal API apps](xref:fundamentals/minimal-apis/parameter-binding) +- [Filters in Minimal API apps](xref:fundamentals/minimal-apis/min-api-filters) \ No newline at end of file diff --git a/aspnetcore/fundamentals/minimal-apis/security.md b/aspnetcore/fundamentals/minimal-apis/security.md index 28c2652d1219..16bc0cf9053a 100644 --- a/aspnetcore/fundamentals/minimal-apis/security.md +++ b/aspnetcore/fundamentals/minimal-apis/security.md @@ -1,60 +1,72 @@ --- title: Authentication and authorization in Minimal APIs author: wadepickett -description: Learn how to configure authentication and authorization in Minimal API apps +description: Learn how to configure authentication and authorization in Minimal API apps, explore concepts, define policies, and run development tests. ms.author: wpickett content_well_notification: AI-contribution monikerRange: '>= aspnetcore-7.0' -ms.date: 9/17/2023 +ms.date: 04/28/2026 uid: fundamentals/minimal-apis/security ai-usage: ai-assisted + +# customer intent: As an ASP.NET developer, I want to use authentication and authorization in Minimal API apps, so I can manage user access to my apps. --- # Authentication and authorization in Minimal APIs [!INCLUDE[](~/includes/not-latest-version.md)] -Minimal APIs support all the authentication and authorization options available in ASP.NET Core and provide some additional functionality to improve the experience working with authentication. +Minimal APIs support all authentication and authorization options available in ASP.NET Core, and provide extra functionality to improve the experience for managing authentication. + +This article describes the support for authentication and authorization in Minimal API applications, and how to configure and test the functionality. + +## Compare authentication and authorization + +Authentication is the process of determining a user's identity while authorization is the process of determining whether a user has access to a resource. Both authentication and authorization scenarios share similar implementation semantics in ASP.NET Core. -## Key concepts in authentication and authorization +- The authentication service, [IAuthenticationService](/dotnet/api/microsoft.aspnetcore.authentication.iauthenticationservice), handles all authentication and is used by authentication [middleware](./middleware.md). +- The authorization service, [IAuthorizationService](/dotnet/api/microsoft.aspnetcore.authorization.iauthorizationservice), manages all authorization and is used by the authorization middleware. -Authentication is the process of determining a user's identity. Authorization is the process of determining whether a user has access to a resource. Both authentication and authorization scenarios share similar implementation semantics in ASP.NET Core. Authentication is handled by the authentication service, [IAuthenticationService](/dotnet/api/microsoft.aspnetcore.authentication.iauthenticationservice), which is used by authentication [middleware](/aspnet/core/fundamentals/middleware). Authorization is handled by the authorization service, [IAuthorizationService](/dotnet/api/microsoft.aspnetcore.authorization.iauthorizationservice), which is used by the authorization middleware. +### Authentication service The authentication service uses registered authentication handlers to complete authentication-related actions. For example, an authentication-related action is authenticating a user or signing out a user. Authentication schemes are names that are used to uniquely identify an authentication handler and its configuration options. Authentication handlers are responsible for implementing the strategies for authentication and generating a user's claims given a particular authentication strategy, such as OAuth or OIDC. The configuration options are unique to the strategy as well and provide the handler with configuration that affects authentication behavior, such as redirect URIs. -There are two strategies for determining user access to resources in the authorization layer: +### Authorization service -* Role-based strategies determine a user's access based on the role they are assigned, such as `Administrator` or `User`. For more information on role-based authorization, see [role-based authorization documentation](/aspnet/core/security/authorization/roles). -* Claim-based strategies determine a user's access based on claims that are issued by a central authority. For more information on claim-based authorization, see [claim-based authorization documentation](/aspnet/core/security/authorization/claims). +In the authorization layer, there are two strategies for determining user access to resources: -In ASP.NET Core, both strategies are captured into an authorization requirement. The authorization service leverages authorization handlers to determine whether or not a particular user meets the authorization requirements applied onto a resource. +- **Role-based strategies** determine a user's access based on their assigned role, such as `Administrator` or `User`. For more information on role-based authorization, see [role-based authorization documentation](../../security/authorization/roles.md). -## Enabling authentication in minimal apps +- **Claim-based strategies** determine a user's access based on claims issued by a central authority. For more information on claim-based authorization, see [claim-based authorization documentation](../../security/authorization/claims.md). -To enable authentication, call [`AddAuthentication`](/dotnet/api/microsoft.extensions.dependencyinjection.authenticationservicecollectionextensions.addauthentication) to register the required authentication services on the app's service provider. +In ASP.NET Core, both strategies are captured into an authorization requirement. The authorization service exercises authorization handlers to determine whether or not a particular user meets the authorization requirements to a resource. + +## Enable authentication in minimal apps + +To enable authentication, call the [AddAuthentication](/dotnet/api/microsoft.extensions.dependencyinjection.authenticationservicecollectionextensions.addauthentication) to register the required authentication services on the app's service provider. :::code language="csharp" source="~/fundamentals/minimal-apis/security/7.0-samples/MinApiAuth/MinApiAuth/Program.cs" id="snippet_1" highlight="2"::: -Typically, a specific authentication strategy is used. In the following sample, the app is configured with support for JWT bearer-based authentication. This example makes use of the APIs available in the [`Microsoft.AspNetCore.Authentication.JwtBearer`](https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.JwtBearer) NuGet package. +Typically, a specific authentication strategy is used. In the following sample, the app is configured with support for JSON Web Token (JWT) bearer-based authentication. This example makes use of the APIs available in the [Microsoft.AspNetCore.Authentication.JwtBearer](https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.JwtBearer) NuGet package. :::code language="csharp" source="~/fundamentals/minimal-apis/security/7.0-samples/MinApiAuth/MinApiAuth/Program.cs" id="snippet_jwt1" highlight="2-3"::: -By default, the [`WebApplication`](/dotnet/api/microsoft.aspnetcore.builder.webapplication) automatically registers the authentication and authorization middlewares if certain authentication and authorization services are enabled. In the following sample, it's not necessary to invoke [`UseAuthentication`](/dotnet/api/microsoft.aspnetcore.builder.authappbuilderextensions.useauthentication) or [`UseAuthorization`](/dotnet/api/microsoft.aspnetcore.builder.authorizationappbuilderextensions.useauthorization) to register the middlewares because [`WebApplication`](/dotnet/api/microsoft.aspnetcore.builder.webapplication) does this automatically after `AddAuthentication` or `AddAuthorization` are called. +By default, the [WebApplication](/dotnet/api/microsoft.aspnetcore.builder.webapplication) automatically registers the authentication and authorization middleware if certain authentication and authorization services are enabled. In the following sample, it's not necessary to invoke the [UseAuthentication](/dotnet/api/microsoft.aspnetcore.builder.authappbuilderextensions.useauthentication) or [UseAuthorization](/dotnet/api/microsoft.aspnetcore.builder.authorizationappbuilderextensions.useauthorization) methods to register the middleware. [WebApplication](/dotnet/api/microsoft.aspnetcore.builder.webapplication) automatically completes the registration after calling the `AddAuthentication` or `AddAuthorization` method. :::code language="csharp" source="~/fundamentals/minimal-apis/security/7.0-samples/MinApiAuth/MinApiAuth/Program.cs" id="snippet_jwt2"::: -In some cases, such as controlling middleware order, it's necessary to explicitly register authentication and authorization. In the following sample, the authentication middleware runs _after_ the CORS middleware has run. For more information on middlewares and this automatic behavior, see [Middleware in Minimal API apps](/aspnet/core/fundamentals/minimal-apis/middleware). +In some cases, such as controlling middleware order, it's necessary to explicitly register authentication and authorization. In the following sample, the authentication middleware runs _after_ the CORS middleware runs. For more information on middleware and this automatic behavior, see [Middleware in Minimal API apps](./middleware.md). :::code language="csharp" source="~/fundamentals/minimal-apis/security/7.0-samples/MinApiAuth/MinApiAuth/Program.cs" id="snippet_after" highlight="9-11"::: -### Configuring authentication strategy +### Configure authentication strategy -Authentication strategies typically support a variety of configurations that are loaded via options. Minimal apps support loading options from configuration for the following authentication strategies: +Authentication strategies typically support various configurations that are loaded via options. Minimal apps support loading options from configuration for the following authentication strategies: -* [JWT bearer-based](https://jwt.io/introduction) -* [OpenID Connection-based](https://openid.net/developers/how-connect-works/) +* [JWT bearer-based authentication](https://jwt.io/introduction#what-is-json-web-token) +* [OpenID Connect, connection-based authentication](https://openid.net/developers/how-connect-works/) -The ASP.NET Core framework expects to find these options under the `Authentication:Schemes:{SchemeName}` section in [configuration](/aspnet/core/fundamentals/configuration). In the following sample, two different schemes, `Bearer` and `LocalAuthIssuer`, are defined with their respective options. The `Authentication:DefaultScheme` option can be used to configure the default authentication strategy that's used. +The ASP.NET Core framework expects to find these options under the `Authentication:Schemes:{SchemeName}` section in the [configuration](../configuration/index.md). In the following sample, two different schemes, `Bearer` and `LocalAuthIssuer`, are defined with their respective options. The `Authentication:DefaultScheme` option can be used to configure the default authentication strategy. ```json { @@ -80,63 +92,68 @@ The ASP.NET Core framework expects to find these options under the `Authenticati } ``` -In `Program.cs`, two JWT bearer-based authentication strategies are registered, with the: +In the _Program.cs_ file, two JWT bearer-based authentication strategies are registered with the following scheme names: -* "Bearer" scheme name. -* "LocalAuthIssuer" scheme name. +* "Bearer" +* "LocalAuthIssuer" -"Bearer" is the typical default scheme in JWT-bearer based enabled apps, but the default scheme can be overridden by setting the `DefaultScheme` property as in the preceding example. +"Bearer" is the typical default scheme in JWT-bearer based enabled apps. However, you can override the default scheme by setting the `DefaultScheme` property as shown in the previous example. -The scheme name is used to uniquely identify an authentication strategy and is used as the lookup key when resolving authentication options from config, as shown in the following example: +The scheme name is used to uniquely identify an authentication strategy. The name is also used as the lookup key when resolving authentication options from config, as shown in the following example: :::code language="csharp" source="~/fundamentals/minimal-apis/security/7.0-samples/MinApiAuth/MinApiAuth/Program.cs" id="snippet_local" highlight="5"::: -## Configuring authorization policies in minimal apps +## Configure authorization policies in minimal apps -Authentication is used to identify and validate the identity of users against an API. Authorization is used to validate and verify access to resources in an API and is facilitated by the `IAuthorizationService` registered by the `AddAuthorization` extension method. In the following scenario, a `/hello` resource is added that requires a user to present an `admin` role claim with a `greetings_api` scope claim. +Authentication identifies and validates the identity of users against an API. Authorization validates and verifies access to resources in an API. The `IAuthorizationService` service registered by the `AddAuthorization` extension method facilitates the authorization. In the following scenario, a `/hello` resource is added that requires a user to present an `admin` role claim with a `greetings_api` scope claim. -Configuring authorization requirements on a resource is a two-step process that requires: +Configuration of the authorization requirements on a resource is a two-step process: -1. Configuring the authorization requirements in a policy globally. -2. Applying individual policies to resources. +1. Define the authorization requirements in a policy globally. +1. Apply individual policies to resources. -In the following code, is invoked which: +In the following code, the is invoked which: * Adds authorization-related services to the DI container. -* Returns an that can be used to directly register authorization policies. +* Returns an object that can be used to directly register authorization policies. -The code creates a new authorization policy, named `admin_greetings`, that encapsulates two authorization requirements: +The code creates a new authorization policy named `admin_greetings` that encapsulates two authorization requirements: -* A role-based requirement via for users with an `admin` role. -* A claim-based requirement via that the user must provide a `greetings_api` scope claim. +* A role-based requirement via the for users with an `admin` role. +* A claim-based requirement via the for which the user must provide a `greetings_api` scope claim. -The `admin_greetings` policy is provided as a required policy to the `/hello` endpoint. +The `admin_greetings` policy is provided as a required policy to the `/hello` endpoint: :::code language="csharp" source="~/fundamentals/minimal-apis/security/7.0-samples/MinApiAuth/MinApiAuth/Program.cs" id="snippet_greet" highlight="5-9,13-14"::: -## Use `dotnet user-jwts` for development testing +## Use 'dotnet user-jwts' for development testing -Throughout this article, an app configured with JWT-bearer based authentication is used. JWT bearer-based authentication requires that clients present a token in the request header to validate their identity and claims. Typically, these tokens are issued by a central authority, such as an identity server. +The examples in this article use an app configured with JWT-bearer based authentication. JWT bearer-based authentication requires clients to present a token in the request header, which is used to validate their identity and claims. Typically, a central authority like an identity server issues the tokens. -When developing on the local machine, the [`dotnet user-jwts`](/aspnet/core/security/authentication/jwt-authn) tool can be used to create bearer tokens. +For development on the local machine, the [dotnet user-jwts](../../security/authentication/jwt-authn.md) command-line tool can be used to create bearer tokens. ```dotnetcli dotnet user-jwts create ``` > [!NOTE] -> When invoked on a project, the tool automatically adds the authentication options matching the generated token to `appsettings.json`. +> When invoked on a project, the tool automatically adds the authentication options that match the generated token to the _appsettings.json_ file. -Tokens can be configured with a variety of customizations. For example, to create a token for the `admin` role and `greetings_api` scope expected by the authorization policy in the preceding code: +Tokens can be configured with various customizations. For example, to create a token for the `admin` role and `greetings_api` scope expected by the authorization policy in the preceding code, run the tool as follows: ```dotnetcli dotnet user-jwts create --scope "greetings_api" --role "admin" ``` -The generated token can then be sent as part of the header in the testing tool of choice. For example, with curl: +The generated token can then be sent as part of the header in the testing tool of choice. For example, to send the token with curl: ```dotnetcli curl -i -H "Authorization: Bearer {token}" https://localhost:{port}/hello ``` -For more information on the `dotnet user-jwts` tool, read the [complete documentation](/aspnet/core/security/authentication/jwt-authn). +## Related content + +- [The authentication service (IAuthenticationService)](/dotnet/api/microsoft.aspnetcore.authentication.iauthenticationservice) +- [The authorization service (IAuthorizationService)](/dotnet/api/microsoft.aspnetcore.authorization.iauthorizationservice) +- [ASP.NET Core Middleware](./middleware.md) +- [Manage JSON Web Tokens with the dotnet user-jwts tool](../../security/authentication/jwt-authn.md) \ No newline at end of file diff --git a/aspnetcore/includes/route-groups.md b/aspnetcore/includes/route-groups.md index cd8181181d48..73af3f4a4f3e 100644 --- a/aspnetcore/includes/route-groups.md +++ b/aspnetcore/includes/route-groups.md @@ -1,4 +1,4 @@ -The extension method helps organize groups of endpoints with a common prefix. It reduces repetitive code and allows for customizing entire groups of endpoints with a single call to methods like and which add [endpoint metadata](xref:fundamentals/routing#endpoint-metadata). +The extension method helps organize groups of endpoints with a common prefix and reduces repetitive code. Use this method to customize entire groups of endpoints with a single call to methods like and that add [endpoint metadata](xref:fundamentals/routing#endpoint-metadata). For example, the following code creates two similar groups of endpoints: @@ -10,23 +10,23 @@ In this scenario, you can use a relative address for the `Location` header in th :::code language="csharp" source="~/fundamentals/minimal-apis/7.0-samples/todo-group/TodoEndpoints.cs" id="snippet_create"::: -The first group of endpoints will only match requests prefixed with `/public/todos` and are accessible without any authentication. The second group of endpoints will only match requests prefixed with `/private/todos` and require authentication. +The first group of endpoints matches only requests prefixed with `/public/todos` and are accessible without any authentication. The second group of endpoints matches only requests prefixed with `/private/todos` and require authentication. -The `QueryPrivateTodos` [endpoint filter factory](xref:fundamentals/minimal-apis/min-api-filters) is a local function that modifies the route handler's `TodoDb` parameters to allow to access and store private todo data. +`QueryPrivateTodos` is a local function that modifies the `TodoDb` parameters of the route handler, to enable them to access and store private todo data. `QueryPrivateTodos` serves as an [endpoint filter factory](xref:fundamentals/minimal-apis/min-api-filters). -Route groups also support nested groups and complex prefix patterns with route parameters and constraints. In the following example, and route handler mapped to the `user` group can capture the `{org}` and `{group}` route parameters defined in the outer group prefixes. +Route groups also support nested groups and complex prefix patterns with route parameters and constraints. In the following example, the route handler mapped to the `user` group can capture the `{org}` and `{group}` route parameters defined in the outer group prefixes. -The prefix can also be empty. This can be useful for adding endpoint metadata or filters to a group of endpoints without changing the route pattern. +The prefix can also be empty. This approach can be useful for adding endpoint metadata or filters to a group of endpoints without changing the route pattern. :::code language="csharp" source="~/fundamentals/minimal-apis/7.0-samples/todo-group/Program.cs" id="snippet_NestedMapGroup1"::: -Adding filters or metadata to a group behaves the same way as adding them individually to each endpoint before adding any extra filters or metadata that may have been added to an inner group or specific endpoint. +Adding filters or metadata to a group results in the same behavior as adding them individually to each endpoint (before adding extra filters or metadata that might exist in an inner group or specific endpoint). :::code language="csharp" source="~/fundamentals/minimal-apis/7.0-samples/todo-group/Program.cs" id="snippet_NestedMapGroup2"::: -In the above example, the outer filter will log the incoming request before the inner filter even though it was added second. Because the filters were applied to different groups, the order they were added relative to each other does not matter. The order filters are added does matter if applied to the same group or specific endpoint. +In the preceding example, the outer filter logs the incoming request before the inner filter even though the outer filter is added second. Because the filters are applied to different groups, the order that they're added relative to each other doesn't matter. The order in which filters are added matters when applied to the same group or specific endpoint. -A request to `/outer/inner/` will log the following: +A request to `/outer/inner/` logs the following data: ```dotnetcli /outer group filter