diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 771ff1c44ddc..761400b478f5 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,7 +1,7 @@ --- author: wadepickett ms.author: wpickett -ms.date: 07-31-2025 +ms.date: 08-17-2025 --- # Copilot Instructions for `dotnet/AspNetCore.Docs` @@ -31,18 +31,40 @@ When creating a PR for an issue: - If you cannot verify, state that explicitly in your output. ### Links and References -- Use relative links (for example, `../folder/file.md` or `./file.md`) when referencing files within this repository. Do not use absolute URLs or GitHub web links for internal content. -- For external links, always remove any language or culture segment from the URL path (such as `/en-us/`, `/fr-fr/`, `/en/`, etc.). - - Example (Microsoft Learn): - - Original: `https://learn.microsoft.com/en-us/aspnet/core/blazor/` - - Correct: `https://learn.microsoft.com/aspnet/core/blazor/` - - Example (Wikipedia): - - Original: `https://en.wikipedia.org/wiki/ASP.NET_Core` - - Correct: `https://wikipedia.org/wiki/ASP.NET_Core` -- For Microsoft Learn links, also strip the base domain (`https://learn.microsoft.com/en-us`) so only the path remains. - - Example: - - Original: `https://learn.microsoft.com/en-us/aspnet/core/blazor/` - - Correct: `/aspnet/core/blazor/` +- For cross-references to other articles within the AspNetCore.Docs repository: + - Use the xref syntax: `` + - The "target-uid" of the xref syntax is obtained from the `uid` property value in the YAML front matter of the article's markdown file + - Examples + - For a target article `uid` value of `aspnetcore/mvc/overview`, the xref cross-link is `` + - For a target article `uid` value of `blazor/index`, the xref cross-link is `` + +- For non-markdown files (files that don't have the `.md` file extension) within this repository, such as PowerShell scripts and code files: + - Use relative links with the appropriate file extension + - Example: `../build-tools/build.ps1` or `./sample.json` + +- For external links to non-Microsoft sites (MDN, W3C, etc.): + - Use absolute URLs + - Remove any language or culture segment from the URL path (such as `/en-us/`, `/fr-fr/`, `/en/`, etc.) + - Example (MDN): + - Original: `https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event` + - Correct: `https://developer.mozilla.org/docs/Web/API/Element/click_event` + +- For links to GitHub repositories: + - Use the full URL path + - Example: `https://github.com/maraf/blazor-wasm-react/blob/main/blazor/Counter.razor` + - Example: `https://github.com/dotnet/blazor-samples/blob/main/10.0/BlazorWebAssemblyReact/blazor/Counter.razor` + - For other Git hosting services or non-Microsoft domains, use the full URL + - Example: `https://gitlab.com/username/repo-name` + +- For links to Microsoft Learn content in other repositories: + - Use the relative URL starting with a forward slash + - Don't include the scheme and the host (example: `https://learn.microsoft.com`) and don't include the locale (example: `en-us`) + - Example: For the target Learn website URL `https://learn.microsoft.com/en-us/dotnet/core/introduction`, use the relative URL `/dotnet/core/introduction` for the link destination + +- Never use physical .md file paths in published content + - Wrong: `../blazor/index.md` or `/aspnet/core/blazor/index.md` + - Correct: `` + - Exception: GitHub-only content (such as README files, contributing guidelines, and other repository documentation that isn't published to learn.microsoft.com) should use an absolute URL to the markdown file (`.md` file extension) ## Repository-Specific Guidelines - Follow the [Microsoft Writing Style Guide](https://learn.microsoft.com/en-us/style-guide/welcome/) @@ -54,7 +76,7 @@ When creating a PR for an issue: - For any new or updated .md file added to the repository, ensure the following frontmatter (metadata) is included: - Metadata `ai-usage: ai-assisted` if any AI assistance was used - Place the title metadata first, followed by the remaining metadata lines in alphabetical order. Example: `title`, `author`, `description`, `monikerRange`, `ms.author`, `ms.custom`, `ms.date`, `uid`, `zone_pivot_groups` - - Metadata `ms.date: ` with a format of MM-DD-YYYY. If the file already has a `ms.date` metadata, update it to today's date if more than 50 characters are changed in the file. + - Metadata `ms.date: ` with a format of MM/DD/YYYY. If the file already has a `ms.date` metadata, update it to today's date if more than 50 characters are changed in the file. ### Version Targeting Common Range Patterns - Fixed Range: `>= aspnetcore-7.0 <= aspnetcore-9.0` @@ -62,6 +84,29 @@ When creating a PR for an issue: - Open Lower Bound: `<= aspnetcore-9.0` - Specific Version: `== aspnetcore-9.0` +### Handling File Redirections +- When a Markdown (.md) article file (this does not apply to includes) is deleted in a PR, create a redirection entry. +- Redirections ensure users following existing links aren't left with broken links +- To add a redirection: + 1. Update the `.openpublishing.redirection.json` file at the repository root + 2. Follow this format for new entries: + ```json + { + "source_path": "aspnetcore/path/to/deleted-file.md", + "redirect_url": "/aspnet/core/path/to/target-file", + "redirect_document_id": false + } + ``` + 3. Use relative URLs for redirection to pages in the `learn.microsoft.com` domain + - Example: `/aspnet/core/path/to/target-file` + 4. For URLs in a different domain, use absolute URLs including the domain. + - Example: `https://learn.microsoft.com/dotnet/core/introduction` + 5. Set `redirect_document_id` to `false` unless specifically instructed otherwise + 6. Maintain alphabetical order of the `source_path` entries for better organization + 7. Ensure proper JSON formatting with correct commas between entries +- When selecting a redirect target, choose the most relevant existing content that would serve the user's original intent +- If no direct replacement exists, redirect to a parent category page or related topic + ### Code Snippets - For code snippets longer than 6 lines: 1. Create a subfolder named after the document the snippet supports. @@ -90,15 +135,15 @@ When creating a PR for an issue: - Use the following language code and indentation standards for markdown code blocks or the `language` attribute of code snippets: Content of the snippet | Language code | Indentation in spaces - :---: | :---: | :---: - C# | csharp | 4 - HTML | html | 4 - CSS | css | 4 - JavaScript | javascript | 2 spaces (use 4 spaces for line continuation) - XML | xml | 2 - JSON | json | 2 - Console | console | 2 - Text | - | 2 + :--------------------: | :-----------: | :-------------------: + C# | csharp | 4 + HTML | html | 4 + CSS | css | 4 + JavaScript | javascript | 2 spaces (use 4 spaces for line continuation) + XML | xml | 2 + JSON | json | 2 + Console | console | 2 + Text | - | 2 ### ASP.NET Core Specific Guidelines - Use the latest supported version for examples unless otherwise specified diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json index 449e5179adec..9cfe8ad57d4a 100644 --- a/.openpublishing.redirection.json +++ b/.openpublishing.redirection.json @@ -1628,6 +1628,31 @@ "source_path": "aspnetcore/blazor/state-management.md", "redirect_url": "/aspnet/core/state-management/", "redirect_document_id": false + }, + { + "source_path": "aspnetcore/fundamentals/includes/apis6.md", + "redirect_url": "/aspnet/core/fundamentals/apis", + "redirect_document_id": false + }, + { + "source_path": "aspnetcore/fundamentals/minimal-apis/handle-errors.md", + "redirect_url": "/aspnet/core/fundamentals/error-handling-api", + "redirect_document_id": false + }, + { + "source_path": "aspnetcore/fundamentals/minimal-apis/overview.md", + "redirect_url": "/aspnet/core/fundamentals/apis", + "redirect_document_id": false + }, + { + "source_path": "aspnetcore/web-api/handle-errors.md", + "redirect_url": "/aspnet/core/fundamentals/error-handling-api", + "redirect_document_id": false + }, + { + "source_path": "aspnetcore/fundamentals/handle-errors.md", + "redirect_url": "/aspnet/core/fundamentals/error-handling-api", + "redirect_document_id": false } ] } diff --git a/aspnetcore/blazor/components/component-disposal.md b/aspnetcore/blazor/components/component-disposal.md index eb531ba20cbf..467e9fc2e3ad 100644 --- a/aspnetcore/blazor/components/component-disposal.md +++ b/aspnetcore/blazor/components/component-disposal.md @@ -12,7 +12,7 @@ uid: blazor/components/component-disposal [!INCLUDE[](~/includes/not-latest-version.md)] -This article explains the ASP.NET Core Razor component disposal with with and . +This article explains the ASP.NET Core Razor component disposal process with and . If a component implements or , the framework calls for resource disposal when the component is removed from the UI. Don't rely on the exact timing of when these methods are executed. For example, can be triggered before or after an asynchronous awaited in [`OnInitalizedAsync`](xref:blazor/components/lifecycle#component-initialization-oninitializedasync) or [`OnParametersSetAsync`](xref:blazor/components/lifecycle#after-parameters-are-set-onparameterssetasync) is called or completes. Also, object disposal code shouldn't assume that objects created during initialization or other lifecycle methods exist. diff --git a/aspnetcore/blazor/forms/validation.md b/aspnetcore/blazor/forms/validation.md index d3462ca411bc..978e280e1800 100644 --- a/aspnetcore/blazor/forms/validation.md +++ b/aspnetcore/blazor/forms/validation.md @@ -597,7 +597,7 @@ app.MapDefaultControllerRoute(); For more information on controller routing and validation failure error responses, see the following resources: * -* +* In the `.Client` project, add the `CustomValidation` component shown in the [Validator components](#validator-components) section. Update the namespace to match the app (for example, `namespace BlazorSample.Client`). diff --git a/aspnetcore/blazor/host-and-deploy/index.md b/aspnetcore/blazor/host-and-deploy/index.md index 25f391be609e..3b2cd1b4eae6 100644 --- a/aspnetcore/blazor/host-and-deploy/index.md +++ b/aspnetcore/blazor/host-and-deploy/index.md @@ -133,10 +133,7 @@ When `WasmBundlerFriendlyBootConfig` is enabled, the produced JS contains `impor The following sample apps are based on [Rollup](https://rollupjs.org/). Similar concepts apply when using other JS bundlers. -Demonstration sample apps: - -* [Blazor WASM in a React application (`maraf/blazor-wasm-react` GitHub repository)](https://github.com/maraf/blazor-wasm-react) -* [.NET on WASM in a React component sample (`maraf/dotnet-wasm-react` GitHub repository)](https://github.com/maraf/dotnet-wasm-react) +Demonstration sample apps for Blazor WebAssembly in a React app (`BlazorWebAssemblyReact`) and .NET on WebAssembly in a React app (`DotNetWebAssemblyReact`) for .NET 10 or later are available in the [Blazor samples GitHub repository (`dotnet/blazor-samples`)](https://github.com/dotnet/blazor-samples). :::moniker-end diff --git a/aspnetcore/blazor/javascript-interoperability/call-javascript-from-dotnet.md b/aspnetcore/blazor/javascript-interoperability/call-javascript-from-dotnet.md index 9cae8fdff679..d38230d405fa 100644 --- a/aspnetcore/blazor/javascript-interoperability/call-javascript-from-dotnet.md +++ b/aspnetcore/blazor/javascript-interoperability/call-javascript-from-dotnet.md @@ -462,8 +462,8 @@ IJSRuntime JS { get; set; } Create an instance of a JS object using a constructor function and get the / .NET handle for referencing the instance with the following API: -* `InvokeNewAsync` (asynchronous) -* `InvokeNew` (synchronous) +* `InvokeConstructorAsync` (asynchronous) +* `InvokeConstructor` (synchronous) Examples in this section demonstrate the API calls with the following `TestClass` with a constructor function (`constructor(text)`): @@ -479,25 +479,25 @@ window.TestClass = class { } ``` -### Asynchronous `InvokeNewAsync` +### Asynchronous `InvokeConstructorAsync` -Use `InvokeNewAsync(string identifier, object?[]? args)` on and to invoke the specified JS constructor function asynchronously. The function is invoked with the `new` operator. In the following example, `TestClass` contains a constructor function, and `classRef` is an . +Use `InvokeConstructorAsync(string identifier, object?[]? args)` on and to invoke the specified JS constructor function asynchronously. The function is invoked with the `new` operator. In the following example, `TestClass` contains a constructor function, and `classRef` is an . ```csharp -var classRef = await JSRuntime.InvokeNewAsync("TestClass", "Blazor!"); +var classRef = await JSRuntime.InvokeConstructorAsync("TestClass", "Blazor!"); var text = await classRef.GetValueAsync("text"); var textLength = await classRef.InvokeAsync("getTextLength"); ``` An overload is available that takes a argument or timeout argument. -### Synchronous `InvokeNew` +### Synchronous `InvokeConstructor` -Use `InvokeNew(string identifier, object?[]? args)` on and to invoke the specified JS constructor function synchronously. The function is invoked with the `new` operator. In the following example, `TestClass` contains a constructor function, and `classRef` is an : +Use `InvokeConstructor(string identifier, object?[]? args)` on and to invoke the specified JS constructor function synchronously. The function is invoked with the `new` operator. In the following example, `TestClass` contains a constructor function, and `classRef` is an : ```csharp var inProcRuntime = ((IJSInProcessRuntime)JSRuntime); -var classRef = inProcRuntime.InvokeNew("TestClass", "Blazor!"); +var classRef = inProcRuntime.InvokeConstructor("TestClass", "Blazor!"); var text = classRef.GetValue("text"); var textLength = classRef.Invoke("getTextLength"); ``` @@ -630,7 +630,7 @@ In server-side scenarios, JS interop calls can't be issued after Blazor's Signal * * * - * `InvokeNewAsync` + * `InvokeConstructorAsync` * `GetValueAsync` * `SetValueAsync` * `Dispose`/`DisposeAsync` calls on any . diff --git a/aspnetcore/blazor/javascript-interoperability/index.md b/aspnetcore/blazor/javascript-interoperability/index.md index bee0906f27ac..297b16dd8aed 100644 --- a/aspnetcore/blazor/javascript-interoperability/index.md +++ b/aspnetcore/blazor/javascript-interoperability/index.md @@ -337,7 +337,7 @@ JavaScript (JS) interop calls can't be issued after Blazor's SignalR circuit is * * * - * `InvokeNewAsync` + * `InvokeConstructorAsync` * `GetValueAsync` * `SetValueAsync` * `Dispose`/`DisposeAsync` calls on any . diff --git a/aspnetcore/blazor/project-structure.md b/aspnetcore/blazor/project-structure.md index 8eb06bf29729..711a2d965acc 100644 --- a/aspnetcore/blazor/project-structure.md +++ b/aspnetcore/blazor/project-structure.md @@ -600,6 +600,12 @@ In a Blazor WebAssembly app, the Blazor script content is located in the `wwwroo ``` +For a Blazor Web App or a Blazor Server app, the project must contain at least one Razor component file (`.razor`) in order to automatically include the Blazor script when the app is published. If the project doesn't contain at least one Razor component, set the `RequiresAspNetWebAssets` MSBuild property `true` in the app's project file to include the Blazor script: + +```xml +true +``` + ## Location of `` and `` content :::moniker range=">= aspnetcore-8.0" @@ -642,7 +648,7 @@ To create an app that can run as either a Blazor Server app or a Blazor WebAssem * * -* +* * [Blazor samples GitHub repository (`dotnet/blazor-samples`)](https://github.com/dotnet/blazor-samples) ([how to download](xref:blazor/fundamentals/index#sample-apps)) :::moniker-end diff --git a/aspnetcore/blazor/security/blazor-web-app-with-oidc.md b/aspnetcore/blazor/security/blazor-web-app-with-oidc.md index 852b03bfaf29..75758c67a11f 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-oidc.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-oidc.md @@ -74,10 +74,16 @@ Sample solution features: For more information on (web) API calls using a service abstractions in Blazor Web Apps, see . +## OIDC provider terminology and guidance + +Although you aren't required to adopt [Microsoft Entra (ME-ID)](https://www.microsoft.com/security/business/microsoft-entra) as the OIDC provider to use the sample app and the guidance in this article, this article describes settings for ME-ID using names that are found in Microsoft documentation and the Azure/Entra portals. OIDC settings have similar naming across OIDC providers. When using a third-party OIDC provider, use the provider's documentation in conjunction with the guidance in this article for app and web API registrations. + ## Microsoft Entra ID app registrations We recommend using separate registrations for apps and web APIs, even when the apps and web APIs are in the same solution. The following guidance is for the `BlazorWebAppOidc` app and `MinimalApiJwt` web API of the sample solution, but the same guidance applies generally to any Entra-based registrations for apps and web APIs. +For app and web API registration guidance, see [Register an application in Microsoft Entra ID](/entra/identity-platform/quickstart-register-app). + Register the web API (`MinimalApiJwt`) first so that you can then grant access to the web API when registering the app. The web API's tenant ID and client ID are used to configure the web API in its `Program` file. After registering the web API, expose the web API in **App registrations** > **Expose an API** with a scope name of `Weather.Get`. Record the App ID URI for use in the app's configuration. Next, register the app (`BlazorWebAppOidc`/`BlazorWebApOidc.Client`) with a **Web** platform configuration and a **Redirect URI** of `https://localhost/signin-oidc` (a port isn't required). The app's tenant ID and client ID, along with the web API's base address, App ID URI, and weather scope name, are used to configure the app in its `Program` file. Grant API permission to access the web API in **App registrations** > **API permissions**. If the app's security specification calls for it, you can grant admin consent for the organization to access the web API. Authorized users and groups are assigned to the app's registration in **App registrations** > **Enterprise applications**. @@ -1459,6 +1465,30 @@ At this point, Razor components can adopt [role-based and policy-based authoriza * Security groups appear in `groups` claims, one claim per group. The security group GUIDs appear in the Azure portal when you create a security group and are listed when selecting **Identity** > **Overview** > **Groups** > **View**. * Built-in ME-ID administrator roles appear in `wids` claims, one claim per role. The `wids` claim with a value of `b79fbf4d-3ef9-4689-8143-76b194e85509` is always sent by ME-ID for non-guest accounts of the tenant and doesn't refer to an administrator role. Administrator role GUIDs (*role template IDs*) appear in the Azure portal when selecting **Roles & admins**, followed by the ellipsis (**…**) > **Description** for the listed role. The role template IDs are also listed in [Microsoft Entra built-in roles (Entra documentation)](/entra/identity/role-based-access-control/permissions-reference). +## Alternative: Duende Access Token Management + +In the sample app, a custom cookie refresher (`CookieOidcRefresher.cs`) implementation is used to perform automatic non-interactive token refresh. An alternative solution can be found in the open source [`Duende.AccessTokenManagement.OpenIdConnect` package](https://docs.duendesoftware.com/accesstokenmanagement/web-apps/). + +Duende Access Token Management provides automatic access token management features for .NET worker and ASP.NET Core web apps, including Blazor, without the need to add a custom cookie refresher. + +After the package is installed, remove the `CookieOidcRefresher` and add access token management for the currently logged-in user in the `Program` file: + +```csharp +// Add services for token management +builder.Services.AddOpenIdConnectAccessTokenManagement(); + +// Register a typed HTTP client with token management support +builder.Services.AddHttpClient(client => + { + client.BaseAddress = new Uri("https://api.example.com/invoices/"); + }) + .AddUserAccessTokenHandler(); +``` + +The [typed HTTP client](xref:blazor/call-web-api#typed-httpclient) (or [named HTTP client](xref:blazor/call-web-api#named-httpclient-with-ihttpclientfactory), if implemented) has automatic access token lifetime management on behalf of the currently logged-in user, including transparent refresh token management. + +For more information, see the [Duende Access Token Management documentation for Blazor](https://docs.duendesoftware.com/accesstokenmanagement/blazor-server/). + ## Troubleshoot [!INCLUDE[](~/blazor/security/includes/troubleshoot-server.md)] diff --git a/aspnetcore/blazor/security/webassembly/standalone-with-identity/index.md b/aspnetcore/blazor/security/webassembly/standalone-with-identity/index.md index 029ec256884f..58ca4753ebcf 100644 --- a/aspnetcore/blazor/security/webassembly/standalone-with-identity/index.md +++ b/aspnetcore/blazor/security/webassembly/standalone-with-identity/index.md @@ -162,7 +162,7 @@ Services and endpoints for [Swagger/OpenAPI](xref:tutorials/web-api-help-pages-u :::moniker-end -User role claims are sent from a [Minimal API](xref:fundamentals/minimal-apis/overview) at the `/roles` endpoint. +User role claims are sent from a [Minimal API](xref:fundamentals/apis) at the `/roles` endpoint. Routes are mapped for Identity endpoints by calling `MapIdentityApi()`. @@ -252,7 +252,7 @@ Role claims aren't sent back from the `manage/info` endpoint to create user clai In the `CookieAuthenticationStateProvider`, a roles request is made to the `/roles` endpoint of the `Backend` server API project. The response is read into a string by calling . deserializes the string into a custom `RoleClaim` array. Finally, the claims are added to the user's claims collection. -In the `Backend` server API's `Program` file, a [Minimal API](xref:fundamentals/minimal-apis/overview) manages the `/roles` endpoint. Claims of are [selected](xref:System.Linq.Enumerable.Select%2A) into an [anonymous type](/dotnet/csharp/fundamentals/types/anonymous-types) and serialized for return to the `BlazorWasmAuth` project with . +In the `Backend` server API's `Program` file, a [Minimal API](xref:fundamentals/apis) manages the `/roles` endpoint. Claims of are [selected](xref:System.Linq.Enumerable.Select%2A) into an [anonymous type](/dotnet/csharp/fundamentals/types/anonymous-types) and serialized for return to the `BlazorWasmAuth` project with . The roles endpoint requires authorization by calling . If you decide not to use Minimal APIs in favor of controllers for secure server API endpoints, be sure to set the [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) on controllers or actions. diff --git a/aspnetcore/blazor/tutorials/movie-database-app/part-1.md b/aspnetcore/blazor/tutorials/movie-database-app/part-1.md index 768ecb3b5e34..7be232743e10 100644 --- a/aspnetcore/blazor/tutorials/movie-database-app/part-1.md +++ b/aspnetcore/blazor/tutorials/movie-database-app/part-1.md @@ -59,36 +59,18 @@ In Visual Studio: * Confirm that the **Location** for the app is suitable. Set the **Place solution and project in the same directory** checkbox to match your preferred solution file location. Select the **Next** button. -:::moniker range=">= aspnetcore-9.0" - -* In the **Additional information** dialog, use the following settings: - - * **Framework**: Select **.NET 9.0 (Standard Term Support)**. - * **Authentication type**: **None** - * **Configure for HTTPS**: Selected - * **Interactive render mode**: **Server** - * **Interactivity location**: **Per page/component** - * **Include sample pages**: Selected - * **Do not use top-level statements**: Not selected - * Select **Create**. - -:::moniker-end - -:::moniker range="< aspnetcore-9.0" - * In the **Additional information** dialog, use the following settings: - * **Framework**: Select **.NET 8.0 (Long Term Support)**. + * **Framework**: Confirm that the [latest framework](https://dotnet.microsoft.com/download/dotnet) is selected. If Visual Studio's **Framework** dropdown list doesn't include the latest available .NET framework, [update Visual Studio](/visualstudio/install/update-visual-studio) and restart the tutorial. * **Authentication type**: **None** * **Configure for HTTPS**: Selected * **Interactive render mode**: **Server** * **Interactivity location**: **Per page/component** * **Include sample pages**: Selected * **Do not use top-level statements**: Not selected + * **Use the .dev.localhost TLD in the application URL**: Not selected * Select **Create**. -:::moniker-end - The Visual Studio instructions in parts of this tutorial series use EF Core commands to add database migrations and update the database. EF Core commands are issued using [Visual Studio Connected Services](/visualstudio/azure/overview-connected-services). More information is provided later in this tutorial series. :::zone-end diff --git a/aspnetcore/blazor/tutorials/signalr-blazor.md b/aspnetcore/blazor/tutorials/signalr-blazor.md index 2730a395acde..7ee11bfee86c 100644 --- a/aspnetcore/blazor/tutorials/signalr-blazor.md +++ b/aspnetcore/blazor/tutorials/signalr-blazor.md @@ -94,6 +94,7 @@ In Visual Studio: * **Interactivity location**: **Per page/component** * **Include sample pages**: Selected * **Do not use top-level statements**: Not selected + * **Use the .dev.localhost TLD in the application URL**: Not selected * Select **Create**. # [Visual Studio Code](#tab/visual-studio-code) @@ -116,13 +117,14 @@ In VS Code: After the preceding changes are made, the **Command Palette** shows the following: - * **Framework**: Set to the latest public non-preview release of .NET. + * **Framework**: Confirm that the [latest framework](https://dotnet.microsoft.com/download/dotnet) is selected. If Visual Studio's **Framework** dropdown list doesn't include the latest available .NET framework, [update Visual Studio](/visualstudio/install/update-visual-studio) and restart the tutorial. * **Authentication type**: **None** - * **Configure for HTTPS**: **true** + * **Configure for HTTPS**: Selected * **Interactive render mode**: **WebAssembly** * **Interactivity location**: **Per page/component** - * **Include sample pages**: **true** - * **Do not use top-level statements**: **false** + * **Include sample pages**: Selected + * **Do not use top-level statements**: Not selected + * **Use the .dev.localhost TLD in the application URL**: Not selected * Select **Create project** from the **Command Palette**. diff --git a/aspnetcore/breadcrumb/toc.yml b/aspnetcore/breadcrumb/toc.yml index 3c13f4bab993..3af76ff8a213 100644 --- a/aspnetcore/breadcrumb/toc.yml +++ b/aspnetcore/breadcrumb/toc.yml @@ -1,3 +1,4 @@ +items: - name: Docs tocHref: / topicHref: / @@ -17,6 +18,9 @@ - name: ASP.NET Core tocHref: /dotnet/core/ topicHref: /aspnet/core/index + - name: ASP.NET Core + tocHref: /dotnet/core/compatibility + topicHref: /aspnet/core/index - name: ASP.NET Core tocHref: /dotnet/standard/ topicHref: /aspnet/core/index diff --git a/aspnetcore/data/ef-mvc/intro/samples/cu-final/Views/Instructors/Index.cshtml b/aspnetcore/data/ef-mvc/intro/samples/cu-final/Views/Instructors/Index.cshtml index ac03615e128f..d78c805f51a8 100644 --- a/aspnetcore/data/ef-mvc/intro/samples/cu-final/Views/Instructors/Index.cshtml +++ b/aspnetcore/data/ef-mvc/intro/samples/cu-final/Views/Instructors/Index.cshtml @@ -26,7 +26,7 @@ string selectedRow = ""; if (item.ID == (int?)ViewData["InstructorID"]) { - selectedRow = "success"; + selectedRow = "table-success"; } @@ -79,7 +79,7 @@ string selectedRow = ""; if (item.CourseID == (int?)ViewData["CourseID"]) { - selectedRow = "success"; + selectedRow = "table-success"; } @@ -122,4 +122,4 @@ } -} \ No newline at end of file +} diff --git a/aspnetcore/data/ef-mvc/intro/samples/cu/Views/Instructors/Index.cshtml b/aspnetcore/data/ef-mvc/intro/samples/cu/Views/Instructors/Index.cshtml index 243b1efcabe2..721c53b20fed 100644 --- a/aspnetcore/data/ef-mvc/intro/samples/cu/Views/Instructors/Index.cshtml +++ b/aspnetcore/data/ef-mvc/intro/samples/cu/Views/Instructors/Index.cshtml @@ -26,7 +26,7 @@ string selectedRow = ""; if (item.ID == (int?)ViewData["InstructorID"]) { - selectedRow = "success"; + selectedRow = "table-success"; } @@ -79,7 +79,7 @@ string selectedRow = ""; if (item.CourseID == (int?)ViewData["CourseID"]) { - selectedRow = "success"; + selectedRow = "table-success"; } diff --git a/aspnetcore/data/ef-mvc/intro/samples/cu/Views/Instructors/Index1.cshtml b/aspnetcore/data/ef-mvc/intro/samples/cu/Views/Instructors/Index1.cshtml index 6681b874f392..39455c41fc88 100644 --- a/aspnetcore/data/ef-mvc/intro/samples/cu/Views/Instructors/Index1.cshtml +++ b/aspnetcore/data/ef-mvc/intro/samples/cu/Views/Instructors/Index1.cshtml @@ -26,7 +26,7 @@ string selectedRow = ""; if (item.ID == (int?)ViewData["InstructorID"]) { - selectedRow = "success"; + selectedRow = "table-success"; } @@ -77,7 +77,7 @@ string selectedRow = ""; if (item.CourseID == (int?)ViewData["CourseID"]) { - selectedRow = "success"; + selectedRow = "table-success"; } diff --git a/aspnetcore/data/ef-rp/intro/samples/cu/Pages/Instructors/Index.cshtml b/aspnetcore/data/ef-rp/intro/samples/cu/Pages/Instructors/Index.cshtml index 7fc8f09fb4f0..cd71caadd6d4 100644 --- a/aspnetcore/data/ef-rp/intro/samples/cu/Pages/Instructors/Index.cshtml +++ b/aspnetcore/data/ef-rp/intro/samples/cu/Pages/Instructors/Index.cshtml @@ -27,7 +27,7 @@ string selectedRow = ""; if (item.ID == Model.InstructorID) { - selectedRow = "success"; + selectedRow = "table-success"; } @@ -80,7 +80,7 @@ string selectedRow = ""; if (item.CourseID == Model.CourseID) { - selectedRow = "success"; + selectedRow = "table-success"; } @@ -123,4 +123,4 @@ } -} \ No newline at end of file +} diff --git a/aspnetcore/data/ef-rp/intro/samples/cu/Pages/Instructors/IndexRRD.cshtml b/aspnetcore/data/ef-rp/intro/samples/cu/Pages/Instructors/IndexRRD.cshtml index b3a446dc586c..7a342771f715 100644 --- a/aspnetcore/data/ef-rp/intro/samples/cu/Pages/Instructors/IndexRRD.cshtml +++ b/aspnetcore/data/ef-rp/intro/samples/cu/Pages/Instructors/IndexRRD.cshtml @@ -27,7 +27,7 @@ string selectedRow = ""; if (item.ID == Model.InstructorID) { - selectedRow = "success"; + selectedRow = "table-success"; } @@ -80,7 +80,7 @@ string selectedRow = ""; if (item.CourseID == Model.CourseID) { - selectedRow = "success"; + selectedRow = "table-success"; } diff --git a/aspnetcore/data/ef-rp/intro/samples/cu20snapshots/cu-part6-related/Pages/Instructors/Index.cshtml b/aspnetcore/data/ef-rp/intro/samples/cu20snapshots/cu-part6-related/Pages/Instructors/Index.cshtml index 8f225c98c44f..70e8dfb30a48 100644 --- a/aspnetcore/data/ef-rp/intro/samples/cu20snapshots/cu-part6-related/Pages/Instructors/Index.cshtml +++ b/aspnetcore/data/ef-rp/intro/samples/cu20snapshots/cu-part6-related/Pages/Instructors/Index.cshtml @@ -27,7 +27,7 @@ string selectedRow = ""; if (item.ID == (int?)ViewData["InstructorID"]) { - selectedRow = "success"; + selectedRow = "table-success"; } @@ -80,7 +80,7 @@ string selectedRow = ""; if (item.CourseID == (int?)ViewData["CourseID"]) { - selectedRow = "success"; + selectedRow = "table-success"; } @@ -123,4 +123,4 @@ } -} \ No newline at end of file +} diff --git a/aspnetcore/data/ef-rp/intro/samples/cu20snapshots/cu-part7/Pages/Instructors/Index.cshtml b/aspnetcore/data/ef-rp/intro/samples/cu20snapshots/cu-part7/Pages/Instructors/Index.cshtml index 8f225c98c44f..70e8dfb30a48 100644 --- a/aspnetcore/data/ef-rp/intro/samples/cu20snapshots/cu-part7/Pages/Instructors/Index.cshtml +++ b/aspnetcore/data/ef-rp/intro/samples/cu20snapshots/cu-part7/Pages/Instructors/Index.cshtml @@ -27,7 +27,7 @@ string selectedRow = ""; if (item.ID == (int?)ViewData["InstructorID"]) { - selectedRow = "success"; + selectedRow = "table-success"; } @@ -80,7 +80,7 @@ string selectedRow = ""; if (item.CourseID == (int?)ViewData["CourseID"]) { - selectedRow = "success"; + selectedRow = "table-success"; } @@ -123,4 +123,4 @@ } -} \ No newline at end of file +} diff --git a/aspnetcore/data/ef-rp/intro/samples/cu20snapshots/cu-part8/Pages/Instructors/Index.cshtml b/aspnetcore/data/ef-rp/intro/samples/cu20snapshots/cu-part8/Pages/Instructors/Index.cshtml index 8f225c98c44f..70e8dfb30a48 100644 --- a/aspnetcore/data/ef-rp/intro/samples/cu20snapshots/cu-part8/Pages/Instructors/Index.cshtml +++ b/aspnetcore/data/ef-rp/intro/samples/cu20snapshots/cu-part8/Pages/Instructors/Index.cshtml @@ -27,7 +27,7 @@ string selectedRow = ""; if (item.ID == (int?)ViewData["InstructorID"]) { - selectedRow = "success"; + selectedRow = "table-success"; } @@ -80,7 +80,7 @@ string selectedRow = ""; if (item.CourseID == (int?)ViewData["CourseID"]) { - selectedRow = "success"; + selectedRow = "table-success"; } @@ -123,4 +123,4 @@ } -} \ No newline at end of file +} diff --git a/aspnetcore/data/ef-rp/read-related-data.md b/aspnetcore/data/ef-rp/read-related-data.md index 97df92ff9d74..0b0fd2e08807 100644 --- a/aspnetcore/data/ef-rp/read-related-data.md +++ b/aspnetcore/data/ef-rp/read-related-data.md @@ -803,13 +803,13 @@ The preceding markup makes the following changes: * Added a **Courses** column that displays courses taught by each instructor. See [Explicit line transition](xref:mvc/views/razor#explicit-line-transition) for more about this razor syntax. -* Added code that dynamically adds `class="success"` to the `tr` element of the selected instructor. This sets a background color for the selected row using a Bootstrap class. +* Added code that dynamically adds `class="table-success"` to the `tr` element of the selected instructor. This sets a background color for the selected row using a Bootstrap class. ```html string selectedRow = ""; if (item.CourseID == Model.CourseID) { - selectedRow = "success"; + selectedRow = "table-success"; } ``` diff --git a/aspnetcore/docfx.json b/aspnetcore/docfx.json index f9bcc3176ff6..d48ead00f5a4 100644 --- a/aspnetcore/docfx.json +++ b/aspnetcore/docfx.json @@ -85,6 +85,9 @@ "**/getting-started/**/**.md": "tutorial", "**/tutorials/**/**.md": "tutorial" }, + "ms.update-cycle": { + "**/**.{md,yml}": "365-days" + }, "no-loc": { "**/**.md": [ "Blazor", "Blazor Hybrid", "Blazor Server", "Blazor WebAssembly", "Blazor Web App", "BREACH", "cookie", "Cookie", "CRIME", "EF Core", "Home" , "global.json", "Identity", "JS", "Kestrel", ".NET Aspire", ".NET MAUI", ".NET Multi-platform App UI", "Privacy", "QuickGrid", "Razor", "REST", "SignalR", "Web View" ] }, diff --git a/aspnetcore/fundamentals/apis.md b/aspnetcore/fundamentals/apis.md index 5467bc507e70..37ce2a5ff4ae 100644 --- a/aspnetcore/fundamentals/apis.md +++ b/aspnetcore/fundamentals/apis.md @@ -1,22 +1,64 @@ --- -title: "APIs overview" -author: tdykstra -description: Learn about differences between controller-based APIs and minimal APIs. -ms.author: tdykstra -ms.date: 4/10/2023 +title: APIs overview +author: JeremyLikness +description: Learn how to build fast HTTP APIs with ASP.NET Core using Minimal APIs, the recommended approach for new projects. +ai-usage: ai-assisted +ms.author: jeliknes +ms.date: 08/15/2025 monikerRange: '>= aspnetcore-6.0' uid: fundamentals/apis --- -# Choose between controller-based APIs and minimal APIs +# APIs overview [!INCLUDE[](~/includes/not-latest-version.md)] :::moniker range=">= aspnetcore-7.0" -ASP.NET Core supports two approaches to creating APIs: a controller-based approach and minimal APIs. *Controllers* in an API project are classes that derive from . *Minimal APIs* define endpoints with logical handlers in lambdas or methods. This article points out differences between the two approaches. +ASP.NET Core provides two approaches for building HTTP APIs: **Minimal APIs** and controller-based APIs. **For new projects, we recommend using Minimal APIs** as they provide a simplified, high-performance approach for building APIs with minimal code and configuration. -The design of minimal APIs hides the host class by default and focuses on configuration and extensibility via extension methods that take functions as lambda expressions. Controllers are classes that can take dependencies via constructor injection or property injection, and generally follow object-oriented patterns. Minimal APIs support dependency injection through other approaches such as accessing the service provider. +## Minimal APIs - Recommended for new projects + +Minimal APIs are the recommended approach for building fast HTTP APIs with ASP.NET Core. They allow you to build fully functioning REST endpoints with minimal code and configuration. Skip traditional scaffolding and avoid unnecessary controllers by fluently declaring API routes and actions. + +Here's a simple example that creates an API at the root of the web app: + +```csharp +var app = WebApplication.Create(args); + +app.MapGet("/", () => "Hello World!"); + +app.Run(); +``` + +Most APIs accept parameters as part of the route: + +```csharp +var builder = WebApplication.CreateBuilder(args); + +var app = builder.Build(); + +app.MapGet("/users/{userId}/books/{bookId}", + (int userId, int bookId) => $"The user id is {userId} and book id is {bookId}"); + +app.Run(); +``` + +Minimal APIs support the configuration and customization needed to scale to multiple APIs, handle complex routes, apply authorization rules, and control the content of API responses. + +### Getting started with Minimal APIs + +* **Tutorial**: +* **Quick reference**: +* **Examples**: For a full list of common scenarios with code examples, see + +## Controller-based APIs - Alternative approach + +ASP.NET Core also supports a controller-based approach where controllers are classes that derive from . This approach follows traditional object-oriented patterns and may be preferred for: + +* Large applications with complex business logic +* Teams familiar with the MVC pattern +* Applications requiring specific MVC features Here's sample code for an API based on controllers: @@ -24,7 +66,7 @@ Here's sample code for an API based on controllers: :::code language="csharp" source="~/fundamentals/apis/APIWithControllers/Controllers/WeatherForecastController.cs"::: -The following code provides the same functionality in a minimal API project. Notice that the minimal API approach involves including the related code in lambda expressions. +The following code provides the same functionality using the recommended Minimal API approach: :::code language="csharp" source="~/fundamentals/apis/MinimalAPI/Program.cs"::: @@ -32,22 +74,91 @@ Both API projects refer to the following class: :::code language="csharp" source="~/fundamentals/apis/APIWithControllers/WeatherForecast.cs"::: -Minimal APIs have many of the same capabilities as controller-based APIs. They support the configuration and customization needed to scale to multiple APIs, handle complex routes, apply authorization rules, and control the content of API responses. There are a few capabilities available with controller-based APIs that are not yet supported or implemented by minimal APIs. These include: +## Choosing between approaches + +**Start with Minimal APIs** for new projects. They offer: + +* **Simpler syntax** - Less boilerplate code +* **Better performance** - Reduced overhead compared to controllers +* **Easier testing** - Simplified unit and integration testing +* **Modern approach** - Leverages the latest .NET features + +**Consider controller-based APIs** if you need: + +* Model binding extensibility (, ) +* Advanced validation features () +* [Application parts](xref:mvc/extensibility/app-parts) or the [application model](xref:mvc/controllers/application-model) +* [JsonPatch](https://www.nuget.org/packages/Microsoft.AspNetCore.JsonPatch/) support +* [OData](https://www.nuget.org/packages/Microsoft.AspNetCore.OData/) support -* No built-in support for model binding (, ). Support can be added with a custom binding shim. -* No built-in support for validation (). -* No support for [application parts](xref:mvc/extensibility/app-parts) or the [application model](xref:mvc/controllers/application-model). There's no way to apply or build your own conventions. -* No built-in view rendering support. We recommend using [Razor Pages](xref:tutorials/razor-pages/razor-pages-start) for rendering views. -* No support for [JsonPatch](https://www.nuget.org/packages/Microsoft.AspNetCore.JsonPatch/) -* No support for [OData](https://www.nuget.org/packages/Microsoft.AspNetCore.OData/) +Most of these features can be implemented in Minimal APIs with custom solutions, but controllers provide them out of the box. ## See also -* . -* -* -* +* - Minimal API tutorial +* - Minimal APIs quick reference +* - Controller-based APIs overview +* - Controller-based API tutorial :::moniker-end -[!INCLUDE[](~/fundamentals/includes/apis6.md)] +:::moniker range="= aspnetcore-6.0" + +ASP.NET Core provides two approaches for building HTTP APIs: **Minimal APIs** and controller-based APIs. **For new projects, we recommend using Minimal APIs** as they provide a simplified, high-performance approach for building APIs with minimal code and configuration. + +## Minimal APIs - Recommended for new projects + +Minimal APIs are the recommended approach for building fast HTTP APIs with ASP.NET Core. They allow you to build fully functioning REST endpoints with minimal code and configuration. + +Here's a simple example: + +```csharp +var app = WebApplication.Create(args); + +app.MapGet("/", () => "Hello World!"); + +app.Run(); +``` + +### Getting started with Minimal APIs + +* **Tutorial**: +* **Quick reference**: + +## Controller-based APIs - Alternative approach + +Controllers are classes that derive from . This approach follows traditional object-oriented patterns. + +Here's sample code for an API based on controllers: + +:::code language="csharp" source="~/fundamentals/apis/APIWithControllers/Program.cs"::: + +:::code language="csharp" source="~/fundamentals/apis/APIWithControllers/Controllers/WeatherForecastController.cs"::: + +The following code provides the same functionality using the recommended Minimal API approach: + +:::code language="csharp" source="~/fundamentals/apis/MinimalAPI/Program.cs"::: + +Both API projects refer to the following class: + +:::code language="csharp" source="~/fundamentals/apis/APIWithControllers/WeatherForecast.cs"::: + +## Choosing between approaches + +**Start with Minimal APIs** for new projects. Consider controller-based APIs if you need: + +* Model binding extensibility (, ) +* Form binding support, including +* Advanced validation features () +* [Application parts](xref:mvc/extensibility/app-parts) or the [application model](xref:mvc/controllers/application-model) +* [JsonPatch](https://www.nuget.org/packages/Microsoft.AspNetCore.JsonPatch/) support +* [OData](https://www.nuget.org/packages/Microsoft.AspNetCore.OData/) support + +## See also + +* - Minimal API tutorial +* - Minimal APIs quick reference +* - Controller-based APIs overview +* - Controller-based API tutorial + +:::moniker-end diff --git a/aspnetcore/fundamentals/error-handling-api.md b/aspnetcore/fundamentals/error-handling-api.md new file mode 100644 index 000000000000..6c35ffdbd532 --- /dev/null +++ b/aspnetcore/fundamentals/error-handling-api.md @@ -0,0 +1,258 @@ +--- +title: Handle errors in ASP.NET Core APIs +author: brunolins16 +description: Learn about error handling in ASP.NET Core APIs with Minimal APIs and controller-based approaches. +ai-usage: ai-assisted +ms.author: wpickett +monikerRange: '>= aspnetcore-7.0' +ms.date: 08/15/2025 +uid: fundamentals/error-handling-api +--- + +# Handle errors in ASP.NET Core APIs + +[!INCLUDE[](~/includes/not-latest-version.md)] + +#### [Minimal APIs](#tab/minimal-apis) + +This article describes how to handle errors in ASP.NET Core APIs. Documentation for Minimal APIs is selected. To see documentation for controller-based APIs, select the **Controllers** tab. For Blazor error handling guidance, see . + +#### [Controllers](#tab/controllers) + +This article describes how to handle errors in ASP.NET Core APIs. Documentation for Controller-based APIs is selected. To see documentation for **Minimal APIs**, select the **Minimal APIs** tab. For Blazor error handling guidance, see . + +--- + +## Developer Exception Page + +[!INCLUDE [](../includes/developer-exception-page.md)] + +#### [Minimal APIs](#tab/minimal-apis) + +To see the Developer Exception Page in a Minimal API: + +* Run the sample app in the [Development environment](xref:fundamentals/environments). +* Go to the `/exception` endpoint. + +This section refers to the following sample app to demonstrate ways to handle exceptions in a Minimal API. It throws an exception when the endpoint `/exception` is requested: + +:::code language="csharp" source="~/fundamentals/minimal-apis/handle-errors/sample8/Program.cs" id="snippet_ThrowExceptions" highlight="4-7"::: + +#### [Controllers](#tab/controllers) + +To see the Developer Exception Page in a controller-based API: + +* Add the following controller action to a controller-based API. The action throws an exception when the endpoint is requested. + + :::code language="csharp" source="~/web-api/handle-errors/samples/6.x/HandleErrorsSample/Controllers/ErrorsController.cs" id="snippet_Throw"::: + +* Run the app in the [development environment](xref:fundamentals/environments). +* Go to the endpoint defined by the controller action. + +--- + +## Exception handler + +In non-development environments, use the [Exception Handler Middleware](xref:fundamentals/error-handling#exception-handler-page) to produce an error payload. + +#### [Minimal APIs](#tab/minimal-apis) + +To configure the `Exception Handler Middleware`, call . For example, the following code changes the app to respond with an [RFC 7807](https://tools.ietf.org/html/rfc7807)-compliant payload to the client. For more information, see the [Problem Details](#problem-details) section later in this article. + +:::code language="csharp" source="~/fundamentals/minimal-apis/handle-errors/sample8/Program.cs" id="snippet_WithUseExceptionHandler" highlight="4-7"::: + +#### [Controllers](#tab/controllers) + +1. In `Program.cs`, call to add the Exception Handling Middleware: + + :::code language="csharp" source="~/web-api/handle-errors/samples/6.x/HandleErrorsSample/Program.cs" id="snippet_Middleware" highlight="7"::: + +1. Configure a controller action to respond to the `/error` route: + + :::code language="csharp" source="~/web-api/handle-errors/samples/6.x/HandleErrorsSample/Controllers/ErrorsController.cs" id="snippet_HandleError"::: + +The preceding `HandleError` action sends an [RFC 7807](https://tools.ietf.org/html/rfc7807)-compliant payload to the client. + +> [!WARNING] +> Don't mark the error handler action method with HTTP method attributes, such as `HttpGet`. Explicit verbs prevent some requests from reaching the action method. +> +> For web APIs that use [Swagger / OpenAPI](xref:tutorials/web-api-help-pages-using-swagger), mark the error handler action with the [[ApiExplorerSettings]](xref:Microsoft.AspNetCore.Mvc.ApiExplorerSettingsAttribute) attribute and set its property to `true`. This attribute configuration excludes the error handler action from the app's OpenAPI specification: +> +> ```csharp +> [ApiExplorerSettings(IgnoreApi = true)] +> ``` +> +> Allow anonymous access to the method if unauthenticated users should see the error. + +--- + +## Client and Server error responses + +#### [Minimal APIs](#tab/minimal-apis) + +Consider the following Minimal API app. + +:::code language="csharp" source="~/fundamentals/minimal-apis/handle-errors/sample8/Program.cs" id="snippet_ClientAndServerErrorResponses"::: + +The `/users` endpoint produces `200 OK` with a `json` representation of `User` when `id` is greater than `0`, otherwise a `400 BAD REQUEST` status code without a response body. For more information about creating a response, see [Create responses in Minimal API apps](/aspnet/core/fundamentals/minimal-apis/responses). + +The [`Status Code Pages middleware`](#client-and-server-error-responses) can be configured to produce a common body content, **when empty**, for all HTTP client (`400`-`499`) or server (`500` -`599`) responses. The middleware is configured by calling the +[UseStatusCodePages]() extension method. + +For example, the following example changes the app to respond with an [RFC 7807](https://tools.ietf.org/html/rfc7807)-compliant payload to the client for all client and server responses, including routing errors (for example, `404 NOT FOUND`). For more information, see the [Problem Details](#problem-details) section. + +:::code language="csharp" source="~/fundamentals/minimal-apis/handle-errors/sample8/Program.cs" id="snippet_ClientAndServerErrorResponsesWithUseStatusCodePages" highlight="4-7"::: + +#### [Controllers](#tab/controllers) + +For controller-based APIs, the error response can be configured in one of the following ways: + +1. Use the [problem details service](#problem-details-service) +1. [Implement ProblemDetailsFactory](#implement-problemdetailsfactory) +1. [Use ApiBehaviorOptions.ClientErrorMapping](#use-apibehavioroptionsclienterrormapping) + +An *error result* is defined as a result with an HTTP status code of 400 or higher. For web API controllers, MVC transforms an error result to produce a . + +The automatic creation of a `ProblemDetails` for error status codes is enabled by default. + +--- + +## Problem details + +[!INCLUDE[](~/includes/problem-details-service.md)] + +#### [Minimal APIs](#tab/minimal-apis) + +Minimal API apps can be configured to generate problem details response for all HTTP client and server error responses that ***don't have body content yet*** by using the `AddProblemDetails` extension method. + +The following code configures the app to generate problem details: + +:::code language="csharp" source="~/fundamentals/minimal-apis/handle-errors/sample8/Program.cs" id="snippet_ProblemDetails" highlight="2"::: + +For more information on using `AddProblemDetails`, see [Problem Details](#problem-details) + +### IProblemDetailsService fallback + +In the following code, `httpContext.Response.WriteAsync("Fallback: An error occurred.")` returns an error if the implementation isn't able to generate a : + +:::code language="csharp" source="~/fundamentals/minimal-apis/handle-errors/sample8/Program.cs" id="snippet_IProblemDetailsServiceWithExceptionFallback" highlight="15"::: + +The preceding code: + +* Writes an error message with the fallback code if the `problemDetailsService` is unable to write a `ProblemDetails`. For example, an endpoint where the [Accept request header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Accept) specifies a media type that the `DefaulProblemDetailsWriter` does not support. +* Uses the [Exception Handler Middleware](#exception-handler). + +The following sample is similar to the preceding except that it calls the [`Status Code Pages middleware`](#client-and-server-error-responses). + +:::code language="csharp" source="~/fundamentals/minimal-apis/handle-errors/sample8/Program.cs" id="snippet_IProblemDetailsServiceWithStatusCodePageFallback" highlight="15"::: + +#### [Controllers](#tab/controllers) + +### Problem details service + +ASP.NET Core supports creating [Problem Details for HTTP APIs](https://www.rfc-editor.org/rfc/rfc9457) using the . + +The following code configures the app to generate a problem details response for all HTTP client and server error responses that ***don't have body content yet***: + +:::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Program.cs" id="snippet_apishort" highlight="4,8-9,13"::: + +Consider the API controller from the preceding section, which returns when the input is invalid: + +:::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Controllers/ValuesController.cs" id="snippet_1"::: + +A problem details response is generated with the preceding code when any of the following conditions apply: + +* An invalid input is supplied. +* The URI has no matching endpoint. +* An unhandled exception occurs. + +#### Customize problem details with `CustomizeProblemDetails` + +The following code uses to set : + +:::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Program.cs" id="snippet_api_controller" highlight="6"::: + +### Implement `ProblemDetailsFactory` + +MVC uses to produce all instances of and . This factory is used for: + +* Client error responses +* Validation failure error responses +* and + +To customize the problem details response, register a custom implementation of in `Program.cs`: + +:::code language="csharp" source="~/web-api/handle-errors/samples/6.x/HandleErrorsSample/Snippets/Program.cs" id="snippet_ReplaceProblemDetailsFactory"::: + +### Use `ApiBehaviorOptions.ClientErrorMapping` + +Use the property to configure the contents of the `ProblemDetails` response. For example, the following code in `Program.cs` updates the property for 404 responses: + +:::code language="csharp" source="~/web-api/handle-errors/samples/6.x/HandleErrorsSample/Snippets/Program.cs" id="snippet_ClientErrorMapping"::: + +--- + +## Additional error handling features + +#### [Minimal APIs](#tab/minimal-apis) + +### Migration from controllers to Minimal APIs + +If you're migrating from controller-based APIs to Minimal APIs: + +1. **Replace action filters** with endpoint filters or middleware +2. **Replace model validation** with manual validation or custom binding +3. **Replace exception filters** with exception handling middleware +4. **Configure problem details** using `AddProblemDetails()` for consistent error responses + +### When to use controller-based error handling + +Consider controller-based APIs if you need: + +* Complex model validation scenarios +* Centralized exception handling across multiple controllers +* Fine-grained control over error response formatting +* Integration with MVC features like filters and conventions + +For detailed information about controller-based error handling, including validation errors, problem details customization, and exception filters, see the [Controllers](?tabs=controllers) tab sections. + +#### [Controllers](#tab/controllers) + +### Validation failure error response + +For web API controllers, MVC responds with a response type when model validation fails. MVC uses the results of to construct the error response for a validation failure. The following example replaces the default factory with an implementation that also supports formatting responses as XML, in `Program.cs`: + +:::code language="csharp" source="~/web-api/handle-errors/samples/6.x/HandleErrorsSample/Snippets/Program.cs" id="snippet_ConfigureInvalidModelStateResponseFactory"::: + +### Use exceptions to modify the response + +The contents of the response can be modified from outside of the controller using a custom exception and an action filter: + +1. Create a well-known exception type named `HttpResponseException`: + + :::code language="csharp" source="~/web-api/handle-errors/samples/6.x/HandleErrorsSample/Snippets/HttpResponseException.cs" id="snippet_Class"::: + +1. Create an action filter named `HttpResponseExceptionFilter`: + + :::code language="csharp" source="~/web-api/handle-errors/samples/6.x/HandleErrorsSample/Snippets/HttpResponseExceptionFilter.cs" id="snippet_Class"::: + + The preceding filter specifies an `Order` of the maximum integer value minus 10. This `Order` allows other filters to run at the end of the pipeline. + +1. In `Program.cs`, add the action filter to the filters collection: + + :::code language="csharp" source="~/web-api/handle-errors/samples/6.x/HandleErrorsSample/Snippets/Program.cs" id="snippet_AddHttpResponseExceptionFilter"::: + +### Key differences for controllers + +* **Automatic model validation**: Controllers automatically validate model state and return `400 Bad Request` responses for validation failures +* **Exception filters**: Use action filters and exception filters for centralized error handling +* **Built-in problem details**: Configure `ApiBehaviorOptions` for standardized error responses +* **Custom error responses**: Override `InvalidModelStateResponseFactory` for custom validation error formatting + +--- + +## Additional resources + +* [How to Use ModelState Validation in ASP.NET Core Web API](https://code-maze.com/aspnetcore-modelstate-validation-web-api/) +* [View or download sample code](https://github.com/dotnet/AspNetCore.Docs.Samples/tree/main/fundamentals/middleware/problem-details-service) +* [Hellang.Middleware.ProblemDetails](https://www.nuget.org/packages/Hellang.Middleware.ProblemDetails/) \ No newline at end of file diff --git a/aspnetcore/fundamentals/error-handling.md b/aspnetcore/fundamentals/error-handling.md index f9b0f5828b13..671995d63f22 100644 --- a/aspnetcore/fundamentals/error-handling.md +++ b/aspnetcore/fundamentals/error-handling.md @@ -14,9 +14,7 @@ uid: fundamentals/error-handling :::moniker range=">= aspnetcore-9.0" -By [Tom Dykstra](https://github.com/tdykstra/) - -This article covers common approaches to handling errors in ASP.NET Core web apps. See also and . +This article covers common approaches to handling errors in ASP.NET Core web apps. See also . For Blazor error handling guidance, which adds to or supersedes the guidance in this article, see . @@ -344,8 +342,7 @@ An alternative approach to generate problem details is to use the third-party Nu * [View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/fundamentals/error-handling/samples) ([how to download](xref:index#how-to-download-a-sample)) * * -* -* . +* :::moniker-end diff --git a/aspnetcore/fundamentals/error-handling/includes/error-handling3-7.md b/aspnetcore/fundamentals/error-handling/includes/error-handling3-7.md index 6018b34f3170..f28328c115e7 100644 --- a/aspnetcore/fundamentals/error-handling/includes/error-handling3-7.md +++ b/aspnetcore/fundamentals/error-handling/includes/error-handling3-7.md @@ -2,7 +2,7 @@ By [Tom Dykstra](https://github.com/tdykstra/) -This article covers common approaches to handling errors in ASP.NET Core web apps. See also and . +This article covers common approaches to handling errors in ASP.NET Core web apps. See also . ## Developer exception page @@ -321,7 +321,7 @@ An alternative approach to generate problem details is to use the third-party Nu By [Tom Dykstra](https://github.com/tdykstra/) -This article covers common approaches to handling errors in ASP.NET Core web apps. See for web APIs. +This article covers common approaches to handling errors in ASP.NET Core web apps. See for web APIs. ## Developer exception page @@ -528,7 +528,7 @@ For information about how to handle model state errors, see [Model binding](xref By [Kirk Larkin](https://twitter.com/serpent5), [Tom Dykstra](https://github.com/tdykstra/), and [Steve Smith](https://ardalis.com/) -This article covers common approaches to handling errors in ASP.NET Core web apps. See for web APIs. +This article covers common approaches to handling errors in ASP.NET Core web apps. See for web APIs. [View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/fundamentals/error-handling/samples). ([How to download](xref:index#how-to-download-a-sample).) The network tab on the F12 browser developer tools is useful when testing the sample app. @@ -785,7 +785,7 @@ For information about how to handle model state errors, see [Model binding](xref By [Tom Dykstra](https://github.com/tdykstra/), and [Steve Smith](https://ardalis.com/) -This article covers common approaches to handling errors in ASP.NET Core web apps. See for web APIs. +This article covers common approaches to handling errors in ASP.NET Core web apps. See for web APIs. [View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/fundamentals/error-handling/samples). ([How to download](xref:index#how-to-download-a-sample).) diff --git a/aspnetcore/fundamentals/error-handling/includes/error-handling8.md b/aspnetcore/fundamentals/error-handling/includes/error-handling8.md index 26e5aeee7adb..9c40f8fdb818 100644 --- a/aspnetcore/fundamentals/error-handling/includes/error-handling8.md +++ b/aspnetcore/fundamentals/error-handling/includes/error-handling8.md @@ -3,7 +3,7 @@ By [Tom Dykstra](https://github.com/tdykstra/) -This article covers common approaches to handling errors in ASP.NET Core web apps. See also and . +This article covers common approaches to handling errors in ASP.NET Core web apps. See also . ## Developer exception page @@ -341,7 +341,7 @@ An alternative approach to generate problem details is to use the third-party Nu * [View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/fundamentals/error-handling/samples) ([how to download](xref:index#how-to-download-a-sample)) * * -* -* . +* +* . :::moniker-end diff --git a/aspnetcore/fundamentals/includes/apis6.md b/aspnetcore/fundamentals/includes/apis6.md deleted file mode 100644 index 910d829f4e73..000000000000 --- a/aspnetcore/fundamentals/includes/apis6.md +++ /dev/null @@ -1,38 +0,0 @@ - :::moniker range="= aspnetcore-6.0" - -ASP.NET Core supports two approaches to creating APIs: a controller-based approach and minimal APIs. *Controllers* in an API project are classes that derive from . *Minimal APIs* define endpoints with logical handlers in lambdas or methods. This article points out differences between the two approaches. - -The design of minimal APIs hides the host class by default and focuses on configuration and extensibility via extension methods that take functions as lambda expressions. Controllers are classes that can take dependencies via constructor injection or property injection, and generally follow object-oriented patterns. Minimal APIs support dependency injection through other approaches such as accessing the service provider. - -Here's sample code for an API based on controllers: - -:::code language="csharp" source="~/fundamentals/apis/APIWithControllers/Program.cs"::: - -:::code language="csharp" source="~/fundamentals/apis/APIWithControllers/Controllers/WeatherForecastController.cs"::: - -The following code provides the same functionality in a minimal API project. Notice that the minimal API approach involves including the related code in lambda expressions. - -:::code language="csharp" source="~/fundamentals/apis/MinimalAPI/Program.cs"::: - -Both API projects refer to the following class: - -:::code language="csharp" source="~/fundamentals/apis/APIWithControllers/WeatherForecast.cs"::: - -Minimal APIs have many of the same capabilities as controller-based APIs. They support the configuration and customization needed to scale to multiple APIs, handle complex routes, apply authorization rules, and control the content of API responses. There are a few capabilities available with controller-based APIs that are not yet supported or implemented by minimal APIs. These include: - -* No built-in support for model binding (, ). Support can be added with a custom binding shim. -* No support for binding from forms. This includes binding . -* No built-in support for validation (). -* No support for [application parts](xref:mvc/extensibility/app-parts) or the [application model](xref:mvc/controllers/application-model). There's no way to apply or build your own conventions. -* No built-in view rendering support. We recommend using [Razor Pages](xref:tutorials/razor-pages/razor-pages-start) for rendering views. -* No support for [JsonPatch](https://www.nuget.org/packages/Microsoft.AspNetCore.JsonPatch/) -* No support for [OData](https://www.nuget.org/packages/Microsoft.AspNetCore.OData/) - -## See also - -* . -* -* -* - -:::moniker-end diff --git a/aspnetcore/fundamentals/index.md b/aspnetcore/fundamentals/index.md index f6b177883e9c..e577f3e3508b 100644 --- a/aspnetcore/fundamentals/index.md +++ b/aspnetcore/fundamentals/index.md @@ -290,7 +290,7 @@ For more information, see [Contribute to the ASP.NET documentation: Code snippet ## Additional resources -* + :::moniker-end diff --git a/aspnetcore/fundamentals/minimal-apis.md b/aspnetcore/fundamentals/minimal-apis.md index 8fc7ce973b6d..9c2a86ff3291 100644 --- a/aspnetcore/fundamentals/minimal-apis.md +++ b/aspnetcore/fundamentals/minimal-apis.md @@ -5,7 +5,7 @@ description: Provides an overview of minimal APIs in ASP.NET Core ms.author: wpickett content_well_notification: AI-contribution monikerRange: '>= aspnetcore-6.0' -ms.date: 05/20/2025 +ms.date: 08/22/2025 uid: fundamentals/minimal-apis ai-usage: ai-assisted --- @@ -39,7 +39,7 @@ The following table lists some of the middleware frequently used with minimal AP | [Authentication](xref:security/authentication/index?view=aspnetcore-6.0) | Provides authentication support. | | | [Authorization](xref:security/authorization/introduction) | Provides authorization support. | | | [CORS](xref:security/cors?view=aspnetcore-6.0) | Configures Cross-Origin Resource Sharing. | | -| [Exception Handler](xref:web-api/handle-errors?view=aspnetcore-6.0) | Globally handles exceptions thrown by the middleware pipeline. | | +| [Exception Handler](xref:fundamentals/error-handling-api?view=aspnetcore-6.0) | Globally handles exceptions thrown by the middleware pipeline. | | | [Forwarded Headers](xref:fundamentals/middleware/index?view=aspnetcore-6.0#forwarded-headers-middleware-order) | Forwards proxied headers onto the current request. | | | [HTTPS Redirection](xref:security/enforcing-ssl?view=aspnetcore-6.0) | Redirects all HTTP requests to HTTPS. | | | [HTTP Strict Transport Security (HSTS)](xref:fundamentals/middleware/index?view=aspnetcore-6.0#middleware-order) | Security enhancement middleware that adds a special response header. | | @@ -56,7 +56,7 @@ The following sections cover request handling: routing, parameter binding, and r ## Routing -A configured `WebApplication` supports `Map{Verb}` and where `{Verb}` is a camel-cased HTTP method like `Get`, `Post`, `Put` or `Delete`: +A configured `WebApplication` supports `Map{Verb}` and where `{Verb}` is a camel-cased HTTP method like `Get`, `Post`, `Put`, or `Delete`: [!code-csharp[](~/fundamentals/minimal-apis/7.0-samples/WebMinAPIs/Program.cs?name=snippet_r1)] @@ -112,6 +112,17 @@ app.MapPost("/products", => TypedResults.Ok(productId)) .DisableValidation(); ``` +### Customize validation error responses using IProblemDetailsService + +Customize error responses from minimal API validation logic with an implementation. Register this service in your application's service collection to enable more consistent and user-specific error responses. Support for minimal API validation was introduced in ASP.NET Core in .NET 10. + +To implement custom validation error responses: + +* Implement or use the default implementation +* Register the service in the DI container +* The validation system automatically uses the registered service to format validation error responses + +For more information on customizing validation error responses with IProblemDetailsService, see . ## Responses @@ -316,7 +327,7 @@ The following code disables `ValidateScopes` and `ValidateOnBuild` in `Developme * * * -* +* * * * [Short-circuit routing](https://andrewlock.net/exploring-the-dotnet-8-preview-short-circuit-routing/) diff --git a/aspnetcore/fundamentals/minimal-apis/10.0-samples/MinApiIproblemDetailsService/MinApiIproblemDetailsService.csproj b/aspnetcore/fundamentals/minimal-apis/10.0-samples/MinApiIproblemDetailsService/MinApiIproblemDetailsService.csproj new file mode 100644 index 000000000000..a3a34b647cd2 --- /dev/null +++ b/aspnetcore/fundamentals/minimal-apis/10.0-samples/MinApiIproblemDetailsService/MinApiIproblemDetailsService.csproj @@ -0,0 +1,9 @@ + + + + net10.0 + enable + enable + + + diff --git a/aspnetcore/fundamentals/minimal-apis/10.0-samples/MinApiIproblemDetailsService/Program.cs b/aspnetcore/fundamentals/minimal-apis/10.0-samples/MinApiIproblemDetailsService/Program.cs new file mode 100644 index 000000000000..d5c3710ff3f2 --- /dev/null +++ b/aspnetcore/fundamentals/minimal-apis/10.0-samples/MinApiIproblemDetailsService/Program.cs @@ -0,0 +1,57 @@ +// +using System.ComponentModel.DataAnnotations; + +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddProblemDetails(options => +{ + options.CustomizeProblemDetails = context => + { + if (context.ProblemDetails.Status == 400) + { + context.ProblemDetails.Title = "Validation error occurred"; + context.ProblemDetails.Extensions["support"] = "Contact support@example.com"; + context.ProblemDetails.Extensions["traceId"] = Guid.NewGuid().ToString(); + } + }; +}); +// + +builder.Services.AddValidation(); + +var app = builder.Build(); + +app.UseHttpsRedirection(); + +// Define endpoints +app.MapGet("/", () => "Hello! Use /products endpoint to test validation with IProblemDetailsService"); + +// Products endpoint that demonstrates validation +app.MapPost("/products", (Product product) => +{ + // If validation passes (handled automatically based on DataAnnotations) + return TypedResults.Ok(product); +}); + +// Explicitly trigger validation failure for testing +app.MapGet("/products/test-validation-error", () => +{ + // Manually create an invalid product to see the validation error + return TypedResults.ValidationProblem(new Dictionary + { + { "Name", new[] { "The Name field is required." } }, + { "Price", new[] { "The field Price must be between 1 and 100." } } + }); +}); + +app.Run(); + +// Model with validation attributes +public class Product +{ + [Required(ErrorMessage = "The Name field is required.")] + public string? Name { get; set; } + + [Range(1, 100, ErrorMessage = "The field Price must be between 1 and 100.")] + public decimal Price { get; set; } +} diff --git a/aspnetcore/fundamentals/minimal-apis/10.0-samples/MinApiIproblemDetailsService/TestIProblemDetailsService.http b/aspnetcore/fundamentals/minimal-apis/10.0-samples/MinApiIproblemDetailsService/TestIProblemDetailsService.http new file mode 100644 index 000000000000..b5034f6c88c2 --- /dev/null +++ b/aspnetcore/fundamentals/minimal-apis/10.0-samples/MinApiIproblemDetailsService/TestIProblemDetailsService.http @@ -0,0 +1,33 @@ +@HostAddress = https://localhost:7134 + +### Test the home endpoint +GET {{HostAddress}} + +### Test products endpoint with valid data +POST {{HostAddress}}/products +Content-Type: application/json + +{ + "name": "Test Product", + "price": 50 +} + +### Test products endpoint with invalid data (missing name) +POST {{HostAddress}}/products +Content-Type: application/json + +{ + "price": 50 +} + +### Test products endpoint with invalid data (price out of range) +POST {{HostAddress}}/products +Content-Type: application/json + +{ + "name": "Test Product", + "price": 200 +} + +### Test explicit validation error endpoint +GET {{HostAddress}}/products/test-validation-error diff --git a/aspnetcore/fundamentals/minimal-apis/10.0-samples/MinApiIproblemDetailsService/appsettings.Development.json b/aspnetcore/fundamentals/minimal-apis/10.0-samples/MinApiIproblemDetailsService/appsettings.Development.json new file mode 100644 index 000000000000..0c208ae9181e --- /dev/null +++ b/aspnetcore/fundamentals/minimal-apis/10.0-samples/MinApiIproblemDetailsService/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/aspnetcore/fundamentals/minimal-apis/10.0-samples/MinApiIproblemDetailsService/appsettings.json b/aspnetcore/fundamentals/minimal-apis/10.0-samples/MinApiIproblemDetailsService/appsettings.json new file mode 100644 index 000000000000..10f68b8c8b4f --- /dev/null +++ b/aspnetcore/fundamentals/minimal-apis/10.0-samples/MinApiIproblemDetailsService/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/aspnetcore/fundamentals/minimal-apis/handle-errors.md b/aspnetcore/fundamentals/minimal-apis/handle-errors.md deleted file mode 100644 index 69b2e49d646d..000000000000 --- a/aspnetcore/fundamentals/minimal-apis/handle-errors.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: Handle errors in minimal APIs -author: brunolins16 -description: Learn about error handling in minimal APIs in ASP.NET Core. -ms.author: wpickett -monikerRange: '>= aspnetcore-7.0' -ms.date: 05/30/2024 -uid: fundamentals/minimal-apis/handle-errors ---- - -# How to handle errors in Minimal API apps - -[!INCLUDE[](~/includes/not-latest-version.md)] - -With contributions by [David Acker](https://github.com/david-acker) - - :::moniker range=">= aspnetcore-8.0" - -This article describes how to handle errors in Minimal API apps. For information about error handling in controller-based APIs, see and . - -## Exceptions - -In a Minimal API app, there are two different built-in centralized mechanisms to handle unhandled exceptions: - -* [Developer Exception Page middleware](#developer-exception-page) (For use in the **Development environment only**.) -* [Exception handler middleware](#exception-handler) - -This section refers to the following sample app to demonstrate ways to handle exceptions in a Minimal API. It throws an exception when the endpoint `/exception` is requested: - -:::code language="csharp" source="~/fundamentals/minimal-apis/handle-errors/sample8/Program.cs" id="snippet_ThrowExceptions" highlight="4-7"::: - -### Developer Exception Page - -[!INCLUDE [](~/includes/developer-exception-page.md)] - -To see the Developer Exception Page: - -* Run the sample app in the [Development environment](xref:fundamentals/environments). -* Go to the `/exception` endpoint. - -### Exception handler - -In non-development environments, use the [Exception Handler Middleware](xref:fundamentals/error-handling#exception-handler-page) to produce an error payload. To configure the `Exception Handler Middleware`, call . - -For example, the following code changes the app to respond with an [RFC 7807](https://tools.ietf.org/html/rfc7807)-compliant payload to the client. For more information, see the [Problem Details](#problem-details) section later in this article. - -:::code language="csharp" source="~/fundamentals/minimal-apis/handle-errors/sample8/Program.cs" id="snippet_WithUseExceptionHandler" highlight="4-7"::: - -## Client and Server error responses - -Consider the following Minimal API app. - -:::code language="csharp" source="~/fundamentals/minimal-apis/handle-errors/sample8/Program.cs" id="snippet_ClientAndServerErrorResponses"::: - -The `/users` endpoint produces `200 OK` with a `json` representation of `User` when `id` is greater than `0`, otherwise a `400 BAD REQUEST` status code without a response body. For more information about creating a response, see [Create responses in Minimal API apps](/aspnet/core/fundamentals/minimal-apis/responses). - -The [`Status Code Pages middleware`](xref:fundamentals/error-handling#sestatuscodepages) can be configured to produce a common body content, **when empty**, for all HTTP client (`400`-`499`) or server (`500` -`599`) responses. The middleware is configured by calling the -[UseStatusCodePages]() extension method. - -For example, the following example changes the app to respond with an [RFC 7807](https://tools.ietf.org/html/rfc7807)-compliant payload to the client for all client and server responses, including routing errors (for example, `404 NOT FOUND`). For more information, see the [Problem Details](#problem-details) section. - -:::code language="csharp" source="~/fundamentals/minimal-apis/handle-errors/sample8/Program.cs" id="snippet_ClientAndServerErrorResponsesWithUseStatusCodePages" highlight="4-7"::: - -## Problem details - -[!INCLUDE[](~/includes/problem-details-service.md)] - -Minimal API apps can be configured to generate problem details response for all HTTP client and server error responses that ***don't have body content yet*** by using the `AddProblemDetails` extension method. - -The following code configures the app to generate problem details: - -:::code language="csharp" source="~/fundamentals/minimal-apis/handle-errors/sample8/Program.cs" id="snippet_ProblemDetails" highlight="2"::: - -For more information on using `AddProblemDetails`, see [Problem Details](/aspnet/core/fundamentals/error-handling?view=aspnetcore-7.0&preserve-view=true#pds7) - -## IProblemDetailsService fallback - -In the following code, `httpContext.Response.WriteAsync("Fallback: An error occurred.")` returns an error if the implementation isn't able to generate a : - -:::code language="csharp" source="~/fundamentals/minimal-apis/handle-errors/sample8/Program.cs" id="snippet_IProblemDetailsServiceWithExceptionFallback" highlight="15"::: - -The preceding code: - -* Writes an error message with the fallback code if the `problemDetailsService` is unable to write a `ProblemDetails`. For example, an endpoint where the [Accept request header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Accept) specifies a media type that the `DefaulProblemDetailsWriter` does not support. -* Uses the [Exception Handler Middleware](xref:fundamentals/error-handling#exception-handler-page). - -The following sample is similar to the preceding except that it calls the [`Status Code Pages middleware`](xref:fundamentals/error-handling#usestatuscodepages). - -:::code language="csharp" source="~/fundamentals/minimal-apis/handle-errors/sample8/Program.cs" id="snippet_IProblemDetailsServiceWithStatusCodePageFallback" highlight="15"::: - -:::moniker-end - -[!INCLUDE[](~/fundamentals/minimal-apis/handle-errors/includes/handle-errors7.md)] diff --git a/aspnetcore/fundamentals/minimal-apis/includes/middleware7.md b/aspnetcore/fundamentals/minimal-apis/includes/middleware7.md index b6420cf4dd5c..0f8a292938a5 100644 --- a/aspnetcore/fundamentals/minimal-apis/includes/middleware7.md +++ b/aspnetcore/fundamentals/minimal-apis/includes/middleware7.md @@ -1,6 +1,6 @@ :::moniker range="= aspnetcore-7.0" -[`WebApplication`](xref:fundamentals/minimal-apis/webapplication) automatically adds the following middleware in [`Minimal API applications`](xref:fundamentals/minimal-apis/overview) depending on certain conditions: +[`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. diff --git a/aspnetcore/fundamentals/minimal-apis/includes/middleware8.md b/aspnetcore/fundamentals/minimal-apis/includes/middleware8.md index 9c806708dc07..e4fac5ce2335 100644 --- a/aspnetcore/fundamentals/minimal-apis/includes/middleware8.md +++ b/aspnetcore/fundamentals/minimal-apis/includes/middleware8.md @@ -1,6 +1,6 @@ :::moniker range=">= aspnetcore-8.0" -[`WebApplication`](xref:fundamentals/minimal-apis/webapplication) automatically adds the following middleware in [`Minimal API applications`](xref:fundamentals/minimal-apis/overview) depending on certain conditions: +[`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. diff --git a/aspnetcore/fundamentals/minimal-apis/includes/minimal-apis6.md b/aspnetcore/fundamentals/minimal-apis/includes/minimal-apis6.md index 8652aa685526..d37aa61d7b80 100644 --- a/aspnetcore/fundamentals/minimal-apis/includes/minimal-apis6.md +++ b/aspnetcore/fundamentals/minimal-apis/includes/minimal-apis6.md @@ -274,7 +274,7 @@ The following table lists some of the middleware frequently used with minimal AP | [Authentication](xref:security/authentication/index?view=aspnetcore-6.0) | Provides authentication support. | | | [Authorization](xref:security/authorization/introduction) | Provides authorization support. | | | [CORS](xref:security/cors?view=aspnetcore-6.0) | Configures Cross-Origin Resource Sharing. | | -| [Exception Handler](xref:web-api/handle-errors?view=aspnetcore-6.0) | Globally handles exceptions thrown by the middleware pipeline. | | +| [Exception Handler](xref:fundamentals/error-handling-api?view=aspnetcore-6.0) | Globally handles exceptions thrown by the middleware pipeline. | | | [Forwarded Headers](xref:fundamentals/middleware/index?view=aspnetcore-6.0#forwarded-headers-middleware-order) | Forwards proxied headers onto the current request. | | | [HTTPS Redirection](xref:security/enforcing-ssl?view=aspnetcore-6.0) | Redirects all HTTP requests to HTTPS. | | | [HTTP Strict Transport Security (HSTS)](xref:fundamentals/middleware/index?view=aspnetcore-6.0#middleware-order) | Security enhancement middleware that adds a special response header. | | diff --git a/aspnetcore/fundamentals/minimal-apis/includes/minimal-apis7.md b/aspnetcore/fundamentals/minimal-apis/includes/minimal-apis7.md index 3f2b86490546..f253c47fce2f 100644 --- a/aspnetcore/fundamentals/minimal-apis/includes/minimal-apis7.md +++ b/aspnetcore/fundamentals/minimal-apis/includes/minimal-apis7.md @@ -21,7 +21,7 @@ The following table lists some of the middleware frequently used with minimal AP | [Authentication](xref:security/authentication/index?view=aspnetcore-6.0) | Provides authentication support. | | | [Authorization](xref:security/authorization/introduction) | Provides authorization support. | | | [CORS](xref:security/cors?view=aspnetcore-6.0) | Configures Cross-Origin Resource Sharing. | | -| [Exception Handler](xref:web-api/handle-errors?view=aspnetcore-6.0) | Globally handles exceptions thrown by the middleware pipeline. | | +| [Exception Handler](xref:fundamentals/error-handling-api?view=aspnetcore-6.0) | Globally handles exceptions thrown by the middleware pipeline. | | | [Forwarded Headers](xref:fundamentals/middleware/index?view=aspnetcore-6.0#forwarded-headers-middleware-order) | Forwards proxied headers onto the current request. | | | [HTTPS Redirection](xref:security/enforcing-ssl?view=aspnetcore-6.0) | Redirects all HTTP requests to HTTPS. | | | [HTTP Strict Transport Security (HSTS)](xref:fundamentals/middleware/index?view=aspnetcore-6.0#middleware-order) | Security enhancement middleware that adds a special response header. | | @@ -224,7 +224,7 @@ Moved to uid: tutorials/min-web-api * * * -* +* * * diff --git a/aspnetcore/fundamentals/minimal-apis/includes/minimal-apis8.md b/aspnetcore/fundamentals/minimal-apis/includes/minimal-apis8.md index b3b7324eb83b..216c54a43ed3 100644 --- a/aspnetcore/fundamentals/minimal-apis/includes/minimal-apis8.md +++ b/aspnetcore/fundamentals/minimal-apis/includes/minimal-apis8.md @@ -21,7 +21,7 @@ The following table lists some of the middleware frequently used with minimal AP | [Authentication](xref:security/authentication/index?view=aspnetcore-6.0) | Provides authentication support. | | | [Authorization](xref:security/authorization/introduction) | Provides authorization support. | | | [CORS](xref:security/cors?view=aspnetcore-6.0) | Configures Cross-Origin Resource Sharing. | | -| [Exception Handler](xref:web-api/handle-errors?view=aspnetcore-6.0) | Globally handles exceptions thrown by the middleware pipeline. | | +| [Exception Handler](xref:fundamentals/error-handling-api?view=aspnetcore-6.0) | Globally handles exceptions thrown by the middleware pipeline. | | | [Forwarded Headers](xref:fundamentals/middleware/index?view=aspnetcore-6.0#forwarded-headers-middleware-order) | Forwards proxied headers onto the current request. | | | [HTTPS Redirection](xref:security/enforcing-ssl?view=aspnetcore-6.0) | Redirects all HTTP requests to HTTPS. | | | [HTTP Strict Transport Security (HSTS)](xref:fundamentals/middleware/index?view=aspnetcore-6.0#middleware-order) | Security enhancement middleware that adds a special response header. | | @@ -255,7 +255,7 @@ The following code disables `ValidateScopes` and `ValidateOnBuild` in `Developme * * * -* +* * * * [Short-circuit routing](https://andrewlock.net/exploring-the-dotnet-8-preview-short-circuit-routing/) diff --git a/aspnetcore/fundamentals/minimal-apis/includes/minimal-apis9.md b/aspnetcore/fundamentals/minimal-apis/includes/minimal-apis9.md index a40d7a39e782..f98f0fbd65de 100644 --- a/aspnetcore/fundamentals/minimal-apis/includes/minimal-apis9.md +++ b/aspnetcore/fundamentals/minimal-apis/includes/minimal-apis9.md @@ -21,7 +21,7 @@ The following table lists some of the middleware frequently used with minimal AP | [Authentication](xref:security/authentication/index?view=aspnetcore-6.0) | Provides authentication support. | | | [Authorization](xref:security/authorization/introduction) | Provides authorization support. | | | [CORS](xref:security/cors?view=aspnetcore-6.0) | Configures Cross-Origin Resource Sharing. | | -| [Exception Handler](xref:web-api/handle-errors?view=aspnetcore-6.0) | Globally handles exceptions thrown by the middleware pipeline. | | +| [Exception Handler](xref:fundamentals/error-handling-api?view=aspnetcore-6.0) | Globally handles exceptions thrown by the middleware pipeline. | | | [Forwarded Headers](xref:fundamentals/middleware/index?view=aspnetcore-6.0#forwarded-headers-middleware-order) | Forwards proxied headers onto the current request. | | | [HTTPS Redirection](xref:security/enforcing-ssl?view=aspnetcore-6.0) | Redirects all HTTP requests to HTTPS. | | | [HTTP Strict Transport Security (HSTS)](xref:fundamentals/middleware/index?view=aspnetcore-6.0#middleware-order) | Security enhancement middleware that adds a special response header. | | @@ -255,7 +255,7 @@ The following code disables `ValidateScopes` and `ValidateOnBuild` in `Developme * * * -* +* * * * [Short-circuit routing](https://andrewlock.net/exploring-the-dotnet-8-preview-short-circuit-routing/) diff --git a/aspnetcore/fundamentals/minimal-apis/middleware.md b/aspnetcore/fundamentals/minimal-apis/middleware.md index b4c529815c6d..a9ba02681de9 100644 --- a/aspnetcore/fundamentals/minimal-apis/middleware.md +++ b/aspnetcore/fundamentals/minimal-apis/middleware.md @@ -17,4 +17,4 @@ uid: fundamentals/minimal-apis/middleware 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. -For more information about Minimal APIs see [`Minimal APIs overview`](xref:fundamentals/minimal-apis/overview). +For more information about Minimal APIs see [APIs overview](xref:fundamentals/apis). diff --git a/aspnetcore/fundamentals/minimal-apis/overview.md b/aspnetcore/fundamentals/minimal-apis/overview.md deleted file mode 100644 index adb142043d88..000000000000 --- a/aspnetcore/fundamentals/minimal-apis/overview.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Minimal APIs overview -author: JeremyLikness -description: An introduction to the fastest and easiest way to create web API endpoints with ASP.NET Core. -ms.author: jeliknes -monikerRange: '>= aspnetcore-6.0' -ms.date: 11/22/2022 -uid: fundamentals/minimal-apis/overview ---- -# Minimal APIs overview - -[!INCLUDE[](~/includes/not-latest-version.md)] - -Minimal APIs are a simplified approach for building fast HTTP APIs with ASP.NET Core. -You can build fully functioning REST endpoints with minimal code and configuration. Skip traditional scaffolding and avoid unnecessary controllers by fluently declaring API routes and actions. For example, the following code creates an API at the root of the web app that returns the text, `"Hello World!"`. - -```csharp -var app = WebApplication.Create(args); - -app.MapGet("/", () => "Hello World!"); - -app.Run(); -``` - -Most APIs accept parameters as part of the route. - -```csharp -var builder = WebApplication.CreateBuilder(args); - -var app = builder.Build(); - -app.MapGet("/users/{userId}/books/{bookId}", - (int userId, int bookId) => $"The user id is {userId} and book id is {bookId}"); - -app.Run(); -``` - -That's all it takes to get started, but it's not all that's available. Minimal APIs support the configuration and customization needed to scale to multiple APIs, handle complex routes, apply authorization rules, and control the content of API responses. A good place to get started is . - -## Want to see some code examples? - -For a full list of common scenarios with code examples, see . - -## Want to jump straight into your first project? - -Build a minimal API app with our tutorial: . diff --git a/aspnetcore/fundamentals/minimal-apis/responses.md b/aspnetcore/fundamentals/minimal-apis/responses.md index 09f826dec11d..522cfa0b4537 100644 --- a/aspnetcore/fundamentals/minimal-apis/responses.md +++ b/aspnetcore/fundamentals/minimal-apis/responses.md @@ -4,14 +4,17 @@ author: brunolins16 description: Learn how to create responses for minimal APIs in ASP.NET Core. ms.author: brolivei monikerRange: '>= aspnetcore-7.0' -ms.date: 05/09/2025 +ms.date: 08/22/2025 uid: fundamentals/minimal-apis/responses +ai-usage: ai-assisted --- # How to create responses in Minimal API apps [!INCLUDE[](~/includes/not-latest-version.md)] +This article explains how to create responses for minimal API endpoints in ASP.NET Core. Minimal APIs provide several ways to return data and HTTP status codes. + :::moniker range=">= aspnetcore-10.0" Minimal endpoints support the following types of return values: @@ -20,6 +23,8 @@ Minimal endpoints support the following types of return values: 1. `T` (Any other type) - This includes `Task` and `ValueTask`. 1. `IResult` based - This includes `Task` and `ValueTask`. +[!INCLUDE[](~/includes/api-endpoint-auth.md)] + ## `string` return values |Behavior|Content-Type| @@ -150,6 +155,24 @@ The preceding example returns a 500 status code. :::code language="csharp" source="~/fundamentals/minimal-apis/9.0-samples/Snippets/Program.cs" id="snippet_12"::: +#### Customize validation error responses using IProblemDetailsService + +Customize error responses from minimal API validation logic with an implementation. Register this service in your application's service collection to enable more consistent and user-specific error responses. Support for minimal API validation was introduced in ASP.NET Core in .NET 10. + +To implement custom validation error responses: + +* Implement or use the default implementation +* Register the service in the DI container +* The validation system automatically uses the registered service to format validation error responses + +The following example shows how to register and configure the to customize validation error responses: + +:::code language="csharp" source="~/fundamentals/minimal-apis/10.0-samples/MinApiIproblemDetailsService/Program.cs" id="snippet_register_IProblemDetailsService_implementation" ::: + +When a validation error occurs, the will be used to generate the error response, including any customizations added in the `CustomizeProblemDetails` callback. + +For a complete app example, see the [Minimal API sample app](https://github.com/dotnet/AspNetCore.Docs/blob/main/aspnetcore/fundamentals/minimal-apis/10.0-samples/MinApiIproblemDetailsService/Program.cs) demonstrating how to customize validation error responses using the in ASP.NET Core Minimal APIs. + #### Text :::code language="csharp" source="~/fundamentals/minimal-apis/9.0-samples/Snippets/Program.cs" id="snippet_08"::: diff --git a/aspnetcore/fundamentals/openapi/include-metadata.md b/aspnetcore/fundamentals/openapi/include-metadata.md index 0b03bb1e2ce1..3b7e6acf6145 100644 --- a/aspnetcore/fundamentals/openapi/include-metadata.md +++ b/aspnetcore/fundamentals/openapi/include-metadata.md @@ -379,7 +379,7 @@ When setting the response type for endpoints that may return a ProblemDetails re * extension method. * with a status code in the (400-499) range. -For more information on how to configure a Minimal API app to return ProblemDetails responses, see . +For more information on how to configure a Minimal API app to return ProblemDetails responses, see . ##### Multiple response types diff --git a/aspnetcore/fundamentals/openapi/includes/include-metadata9.md b/aspnetcore/fundamentals/openapi/includes/include-metadata9.md index 5e1232dd6287..4335e8bf68f8 100644 --- a/aspnetcore/fundamentals/openapi/includes/include-metadata9.md +++ b/aspnetcore/fundamentals/openapi/includes/include-metadata9.md @@ -342,7 +342,7 @@ When setting the response type for endpoints that may return a ProblemDetails re * extension method. * with a status code in the (400-499) range. -For more information on how to configure a Minimal API app to return ProblemDetails responses, see . +For more information on how to configure a Minimal API app to return ProblemDetails responses, see . ##### Multiple response types diff --git a/aspnetcore/fundamentals/openapi/using-openapi-documents.md b/aspnetcore/fundamentals/openapi/using-openapi-documents.md index e53730d2da32..3a60fa9a9d7e 100644 --- a/aspnetcore/fundamentals/openapi/using-openapi-documents.md +++ b/aspnetcore/fundamentals/openapi/using-openapi-documents.md @@ -102,7 +102,7 @@ The output shows any issues with the OpenAPI document. For example: ## Support for injecting `IOpenApiDocumentProvider` -You can inject `Microsoft.AspNetCore.OpenApi.Services.IOpenApiDocumentProvider` into your services through dependency injection to access OpenAPI documents programmatically, even outside HTTP request contexts. +You can inject into your services through dependency injection to access OpenAPI documents programmatically, even outside HTTP request contexts. ```csharp public class DocumentService diff --git a/aspnetcore/fundamentals/servers/kestrel.md b/aspnetcore/fundamentals/servers/kestrel.md index 8d61fcdf606a..d4c1ef0dca1d 100644 --- a/aspnetcore/fundamentals/servers/kestrel.md +++ b/aspnetcore/fundamentals/servers/kestrel.md @@ -5,7 +5,7 @@ description: Learn about Kestrel, the cross-platform web server for ASP.NET Core monikerRange: '>= aspnetcore-3.1' ms.author: tdykstra ms.custom: mvc -ms.date: 08/04/2023 +ms.date: 08/25/2025 uid: fundamentals/servers/kestrel --- # Kestrel web server in ASP.NET Core @@ -47,18 +47,6 @@ For more information on configuring `WebApplication` and `WebApplicationBuilder` For information on apps that must protect a subset of the app with a certificate, see [Optional client certificates](xref:security/authentication/certauth#optional-client-certificates). -## Behavior with debugger attached - -The following timeouts and rate limits aren't enforced when a debugger is attached to a Kestrel process: - -* -* -* -* -* -* -* - [!INCLUDE[](includes/memory-eviction2.md)] @@ -80,9 +68,6 @@ The following timeouts and rate limits aren't enforced when a debugger is attach * [RFC 9110: HTTP Semantics (Section 7.2: Host and :authority)](https://www.rfc-editor.org/rfc/rfc9110#field.host) * When using UNIX sockets on Linux, the socket isn't automatically deleted on app shutdown. For more information, see [this GitHub issue](https://github.com/dotnet/aspnetcore/issues/14134). -> [!NOTE] -> As of .NET 5, Kestrel's libuv transport is obsolete. The libuv transport doesn't receive updates to support new OS platforms, such as Windows ARM64, and will be removed in a future release. Remove any calls to the obsolete method and use Kestrel's default Socket transport instead. - :::moniker-end [!INCLUDE[](~/fundamentals/servers/kestrel/includes/kestrel6.md)] diff --git a/aspnetcore/fundamentals/servers/kestrel/diagnostics.md b/aspnetcore/fundamentals/servers/kestrel/diagnostics.md index c2d3a1509850..af6d77e33828 100644 --- a/aspnetcore/fundamentals/servers/kestrel/diagnostics.md +++ b/aspnetcore/fundamentals/servers/kestrel/diagnostics.md @@ -118,4 +118,4 @@ app.Run(); ## Behavior with debugger attached -Certain timeouts and rate limits aren't enforced when a debugger is attached to a Kestrel process. For more information, see [Behavior with debugger attached](xref:fundamentals/servers/kestrel#behavior-with-debugger-attached). +Certain timeouts and rate limits aren't enforced when a debugger is attached to a Kestrel process. For more information, see [Behavior with debugger attached](xref:fundamentals/servers/kestrel/options#behavior-with-debugger-attached). diff --git a/aspnetcore/fundamentals/servers/kestrel/includes/kestrel6.md b/aspnetcore/fundamentals/servers/kestrel/includes/kestrel6.md index 24807fb25bd4..086459a91196 100644 --- a/aspnetcore/fundamentals/servers/kestrel/includes/kestrel6.md +++ b/aspnetcore/fundamentals/servers/kestrel/includes/kestrel6.md @@ -55,9 +55,6 @@ The following timeouts and rate limits aren't enforced when a debugger is attach * [RFC 9110: HTTP Semantics (Section 7.2: Host and :authority)](https://www.rfc-editor.org/rfc/rfc9110#field.host) * When using UNIX sockets on Linux, the socket isn't automatically deleted on app shutdown. For more information, see [this GitHub issue](https://github.com/dotnet/aspnetcore/issues/14134). -> [!NOTE] -> As of .NET 5, Kestrel's libuv transport is obsolete. The libuv transport doesn't receive updates to support new OS platforms, such as Windows ARM64, and will be removed in a future release. Remove any calls to the obsolete method and use Kestrel's default Socket transport instead. - :::moniker-end :::moniker range=">= aspnetcore-5.0 < aspnetcore-6.0" @@ -107,9 +104,6 @@ For information on apps that must protect a subset of the app with a certificate * [RFC 9110: HTTP Semantics (Section 7.2: Host and :authority)](https://www.rfc-editor.org/rfc/rfc9110#field.host) * When using UNIX sockets on Linux, the socket is not automatically deleted on app shut down. For more information, see [this GitHub issue](https://github.com/dotnet/aspnetcore/issues/14134). -> [!NOTE] -> As of .NET 5, Kestrel's libuv transport is obsolete. The libuv transport doesn't receive updates to support new OS platforms, such as Windows ARM64, and will be removed in a future release. Remove any calls to the obsolete method and use Kestrel's default Socket transport instead. - :::moniker-end :::moniker range="< aspnetcore-5.0" diff --git a/aspnetcore/fundamentals/servers/kestrel/options.md b/aspnetcore/fundamentals/servers/kestrel/options.md index 3d39f16c7a75..a1642a69104b 100644 --- a/aspnetcore/fundamentals/servers/kestrel/options.md +++ b/aspnetcore/fundamentals/servers/kestrel/options.md @@ -5,7 +5,7 @@ description: Learn about configuring options for Kestrel, the cross-platform web monikerRange: '>= aspnetcore-5.0' ms.author: tdykstra ms.custom: mvc -ms.date: 01/26/2023 +ms.date: 08/25/2025 uid: fundamentals/servers/kestrel/options --- # Configure options for the ASP.NET Core Kestrel web server @@ -169,7 +169,15 @@ For information about other Kestrel options and limits, see: ## Behavior with debugger attached -Certain timeouts and rate limits aren't enforced when a debugger is attached to a Kestrel process. For more information, see [Behavior with debugger attached](xref:fundamentals/servers/kestrel#behavior-with-debugger-attached). +The following timeout and rate limit options aren't enforced when a debugger is attached to a Kestrel process: + +* +* +* +* +* +* +* :::moniker-end diff --git a/aspnetcore/includes/api-endpoint-auth.md b/aspnetcore/includes/api-endpoint-auth.md new file mode 100644 index 000000000000..be7235912c86 --- /dev/null +++ b/aspnetcore/includes/api-endpoint-auth.md @@ -0,0 +1,2 @@ +> [!IMPORTANT] +> Starting with ASP.NET Core 10, known API endpoints no longer redirect to login pages when using cookie authentication. Instead, they return 401/403 status codes. For details, see . \ No newline at end of file diff --git a/aspnetcore/log-mon/metrics/built-in.md b/aspnetcore/log-mon/metrics/built-in.md index fe308428ce13..e58fb6dcb627 100644 --- a/aspnetcore/log-mon/metrics/built-in.md +++ b/aspnetcore/log-mon/metrics/built-in.md @@ -129,6 +129,8 @@ Usage: * How many sessions processed? * How long do users keep the session/tab open? +:::moniker-end + ## `Microsoft.AspNetCore.Hosting` The `Microsoft.AspNetCore.Hosting` metrics report high-level information about HTTP requests received by ASP.NET Core: @@ -136,8 +138,6 @@ The `Microsoft.AspNetCore.Hosting` metrics report high-level information about H * [`http.server.request.duration`](#metric-httpserverrequestduration) * [`http.server.active_requests`](#metric-httpserveractive_requests) -:::moniker-end - ### Metric: `http.server.request.duration` Name | Instrument Type | Unit (UCUM) | Description diff --git a/aspnetcore/migration/20_21.md b/aspnetcore/migration/20_21.md index be118e733795..2d8cf4a29001 100644 --- a/aspnetcore/migration/20_21.md +++ b/aspnetcore/migration/20_21.md @@ -245,6 +245,8 @@ For more information, see . ## Breaking changes +Use the articles in [Breaking changes in .NET](/dotnet/core/compatibility/breaking-changes) to find breaking changes that might apply when upgrading an app to a newer version of .NET. + ### FileResult Range header no longer processes the [Accept-Ranges](https://developer.mozilla.org/docs/Web/HTTP/Headers/Accept-Ranges) header by default. To enable the `Accept-Ranges` header, set to `true`. diff --git a/aspnetcore/migration/21-to-22.md b/aspnetcore/migration/21-to-22.md index 9402284f11a5..526d1a3d7d9d 100644 --- a/aspnetcore/migration/21-to-22.md +++ b/aspnetcore/migration/21-to-22.md @@ -29,6 +29,10 @@ This article explains how to update an existing ASP.NET Core 2.1 project to ASP. --- +## Breaking changes + +Use the articles in [Breaking changes in .NET](/dotnet/core/compatibility/breaking-changes) to find breaking changes that might apply when upgrading an app to a newer version of .NET. + ## Update Target Framework Moniker (TFM) Projects targeting .NET Core should use the [TFM](/dotnet/standard/frameworks) of a version greater than or equal to .NET Core 2.2. In the project file, update the `` node's inner text with `netcoreapp2.2`: diff --git a/aspnetcore/migration/22-to-30.md b/aspnetcore/migration/22-to-30.md index df68517a08e7..6858d99d6b1d 100644 --- a/aspnetcore/migration/22-to-30.md +++ b/aspnetcore/migration/22-to-30.md @@ -1159,7 +1159,7 @@ For more information on Razor file compilation, see -## Breaking API changes +## Breaking changes -Review breaking changes: +Use the articles in [Breaking changes in .NET](/dotnet/core/compatibility/breaking-changes) to find breaking changes that might apply when upgrading an app to a newer version of .NET. + +For more information, see the following resources: * [Complete list of breaking changes in the ASP.NET Core 3.0 release](https://github.com/aspnet/Announcements/issues?page=1&q=is%3Aissue+is%3Aopen+label%3A%22Breaking+change%22+label%3A3.0.0) * [Breaking API changes in Antiforgery, CORS, Diagnostics, MVC, and Routing](https://github.com/aspnet/Announcements/issues/387). This list includes breaking changes for compatibility switches. -* For a summary of 2.2-to-3.0 breaking changes across .NET Core, ASP.NET Core, and Entity Framework Core, see [Breaking changes for migration from version 2.2 to 3.0](/dotnet/core/compatibility/2.2-3.0). ## Endpoint routing with catch-all parameter diff --git a/aspnetcore/migration/30-to-31.md b/aspnetcore/migration/30-to-31.md index 77d51c2d2623..39da570ffef5 100644 --- a/aspnetcore/migration/30-to-31.md +++ b/aspnetcore/migration/30-to-31.md @@ -95,9 +95,9 @@ In the `.pubxml` file update the `TargetFramework` to 3.1: + netcoreapp3.1 ``` -## Review breaking changes +## Breaking changes -Review 3.0-to-3.1 breaking changes across .NET Core, ASP.NET Core, and Entity Framework Core at [Breaking changes for migration from version 3.0 to 3.1](/dotnet/core/compatibility/3.0-3.1). +Use the articles in [Breaking changes in .NET](/dotnet/core/compatibility/breaking-changes) to find breaking changes that might apply when upgrading an app to a newer version of .NET. ## Optional changes diff --git a/aspnetcore/migration/31-to-50.md b/aspnetcore/migration/31-to-50.md index 45214ff78989..28d4011ecf59 100644 --- a/aspnetcore/migration/31-to-50.md +++ b/aspnetcore/migration/31-to-50.md @@ -777,6 +777,6 @@ The following tutorials also explain the migration: * [An ASP.NET Core Web app signing-in users with the Microsoft identity platform in your organization](https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/tree/master/1-WebApp-OIDC/1-1-MyOrg#option-2-create-the-sample-from-the-command-line). See **Option 2: Create the sample from the command line**. * [Sign-in a user with the Microsoft identity platform in a WPF Desktop application and call an ASP.NET Core Web API](https://github.com/Azure-Samples/active-directory-dotnet-native-aspnetcore-v2/tree/master/1.%20Desktop%20app%20calls%20Web%20API#how-was-the-code-created). See **How was the code created**. -## Review breaking changes +## Breaking changes -For breaking changes from .NET Core 3.1 to .NET 5, see [Breaking changes for migration from version 3.1 to 5.0](/dotnet/core/compatibility/3.1-5.0). ASP.NET Core and Entity Framework Core are also included in the list. +Use the articles in [Breaking changes in .NET](/dotnet/core/compatibility/breaking-changes) to find breaking changes that might apply when upgrading an app to a newer version of .NET. diff --git a/aspnetcore/migration/31-to-60.md b/aspnetcore/migration/31-to-60.md index 602d49c33892..b2b4a2f62166 100644 --- a/aspnetcore/migration/31-to-60.md +++ b/aspnetcore/migration/31-to-60.md @@ -205,12 +205,11 @@ For more information, see [Obsoleting DatabaseErrorPage middleware (dotnet/aspne [!INCLUDE[](~/includes/appname6.md)] -## Review breaking changes +## Breaking changes -See the following resources: +Use the articles in [Breaking changes in .NET](/dotnet/core/compatibility/breaking-changes) to find breaking changes that might apply when upgrading an app to a newer version of .NET. -* [Identity: Default Bootstrap version of UI changed](/dotnet/core/compatibility/aspnet-core/6.0/identity-bootstrap4-to-5) -* [Breaking changes for migration from version 3.1 to 5.0](/dotnet/core/compatibility/3.1-5.0). ASP.NET Core and Entity Framework Core are also included in the list. -* [Breaking changes for migration from .NET 5 to .NET 6](/dotnet/core/compatibility/6.0): Includes ASP.NET Core and Entity Framework Core. -* [Announcements GitHub repository (aspnet/Announcements, `6.0.0` label)](https://github.com/aspnet/Announcements/issues?q=is%3Aissue+label%3A6.0.0+is%3Aopen): Includes breaking and non-breaking information. -* [Announcements GitHub repository (aspnet/Announcements, `5.0.0` label)](https://github.com/aspnet/Announcements/issues?q=is%3Aissue+label%3A5.0.0+is%3Aopen): Includes breaking and non-breaking information. +For more information, see the following resources: + +* [Announcements GitHub repository (`aspnet/Announcements`, `6.0.0` label)](https://github.com/aspnet/Announcements/issues?q=is%3Aissue+label%3A6.0.0+is%3Aopen): Includes breaking and non-breaking information. +* [Announcements GitHub repository (`aspnet/Announcements`, `5.0.0` label)](https://github.com/aspnet/Announcements/issues?q=is%3Aissue+label%3A5.0.0+is%3Aopen): Includes breaking and non-breaking information. diff --git a/aspnetcore/migration/50-to-60-samples.md b/aspnetcore/migration/50-to-60-samples.md index 29ad17616d40..00c77b23e3f8 100644 --- a/aspnetcore/migration/50-to-60-samples.md +++ b/aspnetcore/migration/50-to-60-samples.md @@ -7,7 +7,6 @@ ms.author: wpickett ms.date: 10/22/2021 uid: migration/50-to-60-samples --- - # Code samples migrated to the new minimal hosting model in ASP.NET Core in .NET 6 +## Breaking changes + +Use the articles in [Breaking changes in .NET](/dotnet/core/compatibility/breaking-changes) to find breaking changes that might apply when upgrading an app to a newer version of .NET. diff --git a/aspnetcore/release-notes/aspnetcore-3.1.md b/aspnetcore/release-notes/aspnetcore-3.1.md index be59650ca86b..52d513668d16 100644 --- a/aspnetcore/release-notes/aspnetcore-3.1.md +++ b/aspnetcore/release-notes/aspnetcore-3.1.md @@ -84,3 +84,7 @@ When a Blazor app isn't functioning properly during development, receiving detai * In production, the gold bar notifies the user that an error has occurred and recommends refreshing the browser. For more information, see . + +## Breaking changes + +Use the articles in [Breaking changes in .NET](/dotnet/core/compatibility/breaking-changes) to find breaking changes that might apply when upgrading an app to a newer version of .NET. diff --git a/aspnetcore/release-notes/aspnetcore-5.0.md b/aspnetcore/release-notes/aspnetcore-5.0.md index 81fe92c7d32d..f37f2e8ec496 100644 --- a/aspnetcore/release-notes/aspnetcore-5.0.md +++ b/aspnetcore/release-notes/aspnetcore-5.0.md @@ -462,3 +462,7 @@ Log messages emitted to the console are JSON formatted: } } ``` + +## Breaking changes + +Use the articles in [Breaking changes in .NET](/dotnet/core/compatibility/breaking-changes) to find breaking changes that might apply when upgrading an app to a newer version of .NET. diff --git a/aspnetcore/release-notes/aspnetcore-6.0.md b/aspnetcore/release-notes/aspnetcore-6.0.md index 76b594bfd835..a63c94ed9368 100644 --- a/aspnetcore/release-notes/aspnetcore-6.0.md +++ b/aspnetcore/release-notes/aspnetcore-6.0.md @@ -702,6 +702,10 @@ In such scenarios, enable shadow copying by customizing the ASP.NET Core module Shadow copying in IIS is an experimental feature that is not guaranteed to be part of ASP.NET Core. Please leave feedback on IIS Shadow copying in [this GitHub issue](https://github.com/dotnet/AspNetCore.Docs/issues/23733). +## Breaking changes + +Use the articles in [Breaking changes in .NET](/dotnet/core/compatibility/breaking-changes) to find breaking changes that might apply when upgrading an app to a newer version of .NET. + ## Additional resources * diff --git a/aspnetcore/release-notes/aspnetcore-7.0.md b/aspnetcore/release-notes/aspnetcore-7.0.md index 520bd46f7d89..d5050dd400cf 100644 --- a/aspnetcore/release-notes/aspnetcore-7.0.md +++ b/aspnetcore/release-notes/aspnetcore-7.0.md @@ -195,7 +195,7 @@ The [`[AsParameters]` attribute](xref:Microsoft.AspNetCore.Http.AsParametersAttr The problem details service implements the interface, which supports creating [Problem Details for HTTP APIs](https://www.rfc-editor.org/rfc/rfc7807.html). -For more information, see [Problem details service](xref:web-api/handle-errors#pds7). +For more information, see [Problem details service](xref:fundamentals/error-handling-api#pds7). ### Route groups @@ -700,3 +700,7 @@ The new [Request decompression middleware](xref:fundamentals/middleware/request- * Eliminates the need to write code to handle compressed requests. For more information, see [Request decompression middleware](xref:fundamentals/middleware/request-decompression?view=aspnetcore-7.0&preserve-view=true). + +## Breaking changes + +Use the articles in [Breaking changes in .NET](/dotnet/core/compatibility/breaking-changes) to find breaking changes that might apply when upgrading an app to a newer version of .NET. diff --git a/aspnetcore/release-notes/aspnetcore-8.0.md b/aspnetcore/release-notes/aspnetcore-8.0.md index 9bfabb0b3331..c677621f5db4 100644 --- a/aspnetcore/release-notes/aspnetcore-8.0.md +++ b/aspnetcore/release-notes/aspnetcore-8.0.md @@ -1062,7 +1062,7 @@ In .NET 7, the [ProblemDetails service](xref:fundamentals/error-handling#problem :::code language="csharp" source="~/fundamentals/minimal-apis/handle-errors/sample8/Program.cs" id="snippet_IProblemDetailsServiceWithExceptionFallback" highlight="15"::: -For more information, see [IProblemDetailsService fallback](xref:fundamentals/minimal-apis/handle-errors#iproblemdetailsservice-fallback) +For more information, see [IProblemDetailsService fallback](xref:fundamentals/error-handling-api#iproblemdetailsservice-fallback) +## Breaking changes + +Use the articles in [Breaking changes in .NET](/dotnet/core/compatibility/breaking-changes) to find breaking changes that might apply when upgrading an app to a newer version of .NET. + ## Additional resources * [Announcing ASP.NET Core in .NET 8 (blog post)](https://devblogs.microsoft.com/dotnet/announcing-asp-net-core-in-dotnet-8/) diff --git a/aspnetcore/release-notes/aspnetcore-9.0.md b/aspnetcore/release-notes/aspnetcore-9.0.md index 71dc31f519f9..65e055ab2ccf 100644 --- a/aspnetcore/release-notes/aspnetcore-9.0.md +++ b/aspnetcore/release-notes/aspnetcore-9.0.md @@ -90,3 +90,7 @@ The following sections describe miscellaneous new features. [!INCLUDE[](~/release-notes/aspnetcore-9/includes/trust_dev_cert_linux.md)] [!INCLUDE[](~/release-notes/aspnetcore-9/includes/updated-versions.md)] + +## Breaking changes + +Use the articles in [Breaking changes in .NET](/dotnet/core/compatibility/breaking-changes) to find breaking changes that might apply when upgrading an app to a newer version of .NET. diff --git a/aspnetcore/security/authentication/api-endpoint-auth.md b/aspnetcore/security/authentication/api-endpoint-auth.md new file mode 100644 index 000000000000..504a8af7fd89 --- /dev/null +++ b/aspnetcore/security/authentication/api-endpoint-auth.md @@ -0,0 +1,79 @@ +--- +title: API endpoint authentication behavior in ASP.NET Core +author: wadepickett +description: Learn how ASP.NET Core 10 and later handles authentication failures for API endpoints using cookie authentication. +ai-usage: ai-assisted +monikerRange: '>= aspnetcore-10.0' +ms.author: wpickett +ms.date: 08/06/2025 +uid: security/authentication/api-endpoint-auth +--- + +# API endpoint authentication behavior in ASP.NET Core + +:::moniker range=">= aspnetcore-10.0" + +When using cookie authentication, API endpoints return the appropriate HTTP status codes (such as 401 or 403) for authentication failures instead of redirecting unauthenticated requests to login pages. This behavior, which is more suitable for programmatic API access, was introduced in ASP.NET Core in .NET 10. + +## How ASP.NET Core identifies API endpoints + +ASP.NET Core automatically applies this behavior to endpoints it recognizes as API-related, including: + +- Controllers decorated with the `[ApiController]` attribute +- Minimal API endpoints registered with `MapGet`, `MapPost`, `MapPut`, `MapDelete`, etc. +- Endpoints that explicitly request JSON responses +- SignalR hubs and endpoints + +## Default behavior and customization + +By default, ASP.NET Core applies cookie authentication logic based on the endpoint type: + +- **Web pages**: Redirect to login pages +- **API endpoints**: Return 401 or 403 status codes without redirects + +## Configuring the behavior + +While the default behavior works for most scenarios, it can be customized if needed: + +```csharp +builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) + .AddCookie(options => + { + options.LoginPath = "/Account/Login"; + // The framework automatically handles API endpoints + // No additional configuration needed + }); +``` + +If you need to override the automatic detection for specific endpoints, use the `[Authorize]` attribute with specific authentication schemes or implement custom authentication handlers. + +## Migration considerations + +This behavior change introduced in .NET 10 is designed to be non-breaking for existing applications: + +- **Web applications**: Continue to work as before with login page redirects +- **Mixed applications**: API endpoints get proper status codes while web pages get redirects +- **API-only applications**: Benefit from proper HTTP status codes without additional configuration + +### Testing your API endpoints + +After upgrading to ASP.NET Core 10, verify that your API endpoints return appropriate status codes: + +```csharp +[Test] +public async Task UnauthorizedApiRequest_Returns401() +{ + var response = await client.GetAsync("/api/secure-data"); + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + Assert.False(response.Headers.Location != null); // No redirect +} +``` + +## Related topics + +- +- +- +- + +:::moniker-end diff --git a/aspnetcore/security/authentication/cookie.md b/aspnetcore/security/authentication/cookie.md index 4914470d6af2..69bf12d04c26 100644 --- a/aspnetcore/security/authentication/cookie.md +++ b/aspnetcore/security/authentication/cookie.md @@ -19,6 +19,11 @@ By [Rick Anderson](https://twitter.com/RickAndMSFT) For demonstration purposes in the sample app, the user account for the hypothetical user, Maria Rodriguez, is hardcoded into the app. Use the **Email** address `maria.rodriguez@contoso.com` and any password to sign in the user. The user is authenticated in the `AuthenticateUser` method in the `Pages/Account/Login.cshtml.cs` file. In a real-world example, the user would be authenticated against a datastore. +:::moniker-end +:::moniker range=">= aspnetcore-10.0" +[!INCLUDE[](~/includes/api-endpoint-auth.md)] +:::moniker-end +:::moniker range=">= aspnetcore-6.0" ## Add cookie authentication * Add the Authentication Middleware services with the and methods. diff --git a/aspnetcore/signalr/authn-and-authz.md b/aspnetcore/signalr/authn-and-authz.md index 9cb9900edf20..c4e1dbe07d97 100644 --- a/aspnetcore/signalr/authn-and-authz.md +++ b/aspnetcore/signalr/authn-and-authz.md @@ -30,6 +30,12 @@ In a browser-based app, cookie authentication allows existing user credentials t Cookies are a browser-specific way to send access tokens, but non-browser clients can send them. When using the [.NET Client](xref:signalr/dotnet-client), the `Cookies` property can be configured in the `.WithUrl` call to provide a cookie. However, using cookie authentication from the .NET client requires the app to provide an API to exchange authentication data for a cookie. +:::moniker-end +:::moniker range=">= aspnetcore-10.0" +[!INCLUDE[](~/includes/api-endpoint-auth.md)] +:::moniker-end +:::moniker range=">= aspnetcore-6.0" + ### Bearer token authentication The client can provide an access token instead of using a cookie. The server validates the token and uses it to identify the user. This validation is done only when the connection is established. During the life of the connection, the server doesn't automatically revalidate to check for token revocation. diff --git a/aspnetcore/test/localhost-tld.md b/aspnetcore/test/localhost-tld.md new file mode 100644 index 000000000000..fa59e6f797eb --- /dev/null +++ b/aspnetcore/test/localhost-tld.md @@ -0,0 +1,62 @@ +--- +author: tdykstra +description: Learn how using localhost as top-level domain can make testing easier in some scenarios. +monikerRange: '>= aspnetcore-10.0' +ms.author: tdykstra +ms.custom: +ms.date: 08/26/2025 +title: Support for the .localhost top-level domain +uid: test/localhost-tld +--- + +# Support for the .localhost top-level domain + +The `.localhost` top-level domain (TLD) is defined in [RFC2606](https://www.rfc-editor.org/rfc/rfc2606) and [RFC6761](https://www.rfc-editor.org/rfc/rfc6761) as being reserved for testing purposes and available for users to use locally as they would any other domain name. This means using a name like `myapp.localhost` locally that resolves to the IP loopback address is allowed and expected according to these RFCs. + +Modern evergreen browsers already automatically resolve any `*.localhost` name to the IP loopback address (`127.0.0.1`/`::1`), effectively making them an alias for any service already being hosted at `localhost` on the local machine. Any service responding to `http://localhost:6789` will also respond to `http://anything-here.localhost:6789`, assuming no further specific hostname verification or enforcement is being performed by the service. + +Having different apps running locally be resolvable via different names allows for better separation of some domain-name-associated website assets (for example, cookies) and makes it easier to identify which app you're browsing via the name displayed in the browser address bar. Support for the .localhost TLD was introduced in ASP.NET Core in .NET 10. + +## Kestrel support for .localhost + +ASP.NET Core's built-in HTTP server, Kestrel, correctly treats any `*.localhost` name set via [supported endpoint configuration mechanisms](xref:fundamentals/servers/kestrel/endpoints?view=aspnetcore-10.0#configure-endpoints) as the local loopback address and binds to it rather than all external addresses (that is, bind to `127.0.0.1`/`::1` rather than `0.0.0.0`/`::`). This includes the `"applicationUrl"` property in [launch profiles configured in a *launchSettings.json* file](xref:fundamentals/environments?view=aspnetcore-10.0#development-and-launchsettingsjson), and the `ASPNETCORE_URLS` environment variable. When configured to listen on a `.localhost` address, Kestrel logs an information message for both the `.localhost` **and** `localhost` addresses, to make it clear that both names can be used. + +## Browser compatibility + +While web browsers automatically resolve `*.localhost` names to the local loopback address, other apps might treat `*.localhost` names as regular domain names and attempt to resolve them via their corresponding DNS stack. If your DNS configuration doesn't resolve `*.localhost` names to an address, they fail to connect. You can continue to use the regular `localhost` name to address your apps when not in a web browser. + +## HTTPS development certificate + +The [ASP.NET Core HTTPS development certificate](xref:security/enforcing-ssl?view=aspnetcore-10.0#trust-the-aspnet-core-https-development-certificate) (including the `dotnet dev-certs https` command) is valid for use with the `*.dev.localhost` domain name. + +The certificate lists the `*.dev.localhost` name as a Subject Alternative Name (SAN) rather than `*.localhost` because using a wildcard certificate for a top-level domain name is invalid. + +## Project template integration + +The project templates for *ASP.NET Core Empty* (`web`) and *Blazor Web App* (`blazor`) have an option that configures the created project to use the `.dev.localhost` domain name suffix. The option combines the domain suffix with the project name to allow the app to be browsed at an address like `https://myapp.dev.localhost:5036`: + +```console +$ dotnet new web -n MyApp --localhost-tld +The template "ASP.NET Core Empty" was created successfully. + +Processing post-creation actions... +Restoring D:\src\MyApp\MyApp.csproj: +Restore succeeded. + +$ cd .\MyApp\ +$ dotnet run --launch-profile https +info: Microsoft.Hosting.Lifetime[14] + Now listening on: https://myapp.dev.localhost:7099 +info: Microsoft.Hosting.Lifetime[14] + Now listening on: https://localhost:7099/ +info: Microsoft.Hosting.Lifetime[14] + Now listening on: http://myapp.dev.localhost:5036 +info: Microsoft.Hosting.Lifetime[14] + Now listening on: http://localhost:5036/ +info: Microsoft.Hosting.Lifetime[0] + Application started. Press Ctrl+C to shut down. +info: Microsoft.Hosting.Lifetime[0] + Hosting environment: Development +info: Microsoft.Hosting.Lifetime[0] + Content root path: D:\src\local\10.0.1xx\MyApp +``` \ No newline at end of file diff --git a/aspnetcore/toc.yml b/aspnetcore/toc.yml index b52599b6b67b..38098e309a9b 100644 --- a/aspnetcore/toc.yml +++ b/aspnetcore/toc.yml @@ -7,18 +7,42 @@ items: uid: get-started - name: What's new items: - - name: What's new in 10 - uid: aspnetcore-10 - - name: What's new in 9 - uid: aspnetcore-9 - - name: What's new in 8 - uid: aspnetcore-8 - - name: What's new in 7 - uid: aspnetcore-7 - - name: What's new in 6 - uid: aspnetcore-6.0 - - name: What's new in 5 - uid: aspnetcore-5.0 + - name: ASP.NET Core 10 + items: + - name: What's new in 10 + uid: aspnetcore-10 + - name: Breaking changes + href: /dotnet/core/compatibility/10.0?toc=/aspnet/core/toc.json&bc=/aspnet/core/breadcrumb/toc.json#aspnet-core + - name: ASP.NET Core 9 + items: + - name: What's new in 9 + uid: aspnetcore-9 + - name: Breaking changes + href: /dotnet/core/compatibility/9.0?toc=/aspnet/core/toc.json&bc=/aspnet/core/breadcrumb/toc.json#aspnet-core + - name: ASP.NET Core 8 + items: + - name: What's new in 8 + uid: aspnetcore-8 + - name: Breaking changes + href: /dotnet/core/compatibility/8.0?toc=/aspnet/core/toc.json&bc=/aspnet/core/breadcrumb/toc.json#aspnet-core + - name: ASP.NET Core 7 + items: + - name: What's new in 7 + uid: aspnetcore-7 + - name: Breaking changes + href: /dotnet/core/compatibility/7.0?toc=/aspnet/core/toc.json&bc=/aspnet/core/breadcrumb/toc.json#aspnet-core + - name: ASP.NET Core 6 + items: + - name: What's new in 6 + uid: aspnetcore-6.0 + - name: Breaking changes + href: /dotnet/core/compatibility/6.0?toc=/aspnet/core/toc.json&bc=/aspnet/core/breadcrumb/toc.json#aspnet-core + - name: ASP.NET Core 5 + items: + - name: What's new in 5 + uid: aspnetcore-5.0 + - name: Breaking changes + href: /dotnet/core/compatibility/5.0?toc=/aspnet/core/toc.json&bc=/aspnet/core/breadcrumb/toc.json#aspnet-core - name: What's new in 3.1 uid: aspnetcore-3.1 - name: What's new in 3.0 @@ -86,6 +110,11 @@ items: uid: blazor/tutorials/index - name: APIs items: + - name: Minimal APIs + items: + - name: Create a minimal web API + displayName: API tutorial + uid: tutorials/min-web-api - name: Controller-based APIs items: - name: Create a controller-based web API @@ -103,11 +132,6 @@ items: - name: Publish to Azure API Management displayName: tutorial uid: tutorials/publish-to-azure-api-management-using-vs - - name: Minimal APIs - items: - - name: Create a minimal web API - displayName: API tutorial - uid: tutorials/min-web-api - name: Real-time web apps items: - name: SignalR with JavaScript @@ -289,7 +313,7 @@ items: uid: fundamentals/error-handling - name: Make HTTP requests displayName: httpclient, httpclientfactory - uid: fundamentals/http-requests + uid: fundamentals/http-requests - name: Map Static files uid: fundamentals/map-static-files - name: Static files @@ -850,6 +874,52 @@ items: items: - name: Overview uid: fundamentals/apis + - name: "Tutorial: Create a minimal API" + uid: tutorials/min-web-api + - name: Minimal APIs quick reference + uid: fundamentals/minimal-apis + - name: WebApplication and WebApplicationBuilder + uid: fundamentals/minimal-apis/webapplication + - name: Route Handlers + uid: fundamentals/minimal-apis/route-handlers + - name: Parameter binding + uid: fundamentals/minimal-apis/parameter-binding + - name: Create responses + uid: fundamentals/minimal-apis/responses + - name: Filters + uid: fundamentals/minimal-apis/min-api-filters + - name: Unit and integration tests + uid: fundamentals/minimal-apis/test-min-api + - name: Middleware + uid: fundamentals/minimal-apis/middleware + - name: Handle errors + uid: fundamentals/error-handling-api + - name: Authentication and authorization + uid: fundamentals/minimal-apis/security + - name: OpenAPI + items: + - name: Overview + uid: fundamentals/openapi/overview + - name: Generate OpenAPI documents + uid: fundamentals/openapi/aspnetcore-openapi + - name: Include OpenAPI metadata + uid: fundamentals/openapi/include-metadata + - name: XML doc comment support + uid: fundamentals/openapi/aspnet-openapi-xml + - name: Customize OpenAPI documents + uid: fundamentals/openapi/customize-openapi + - name: Use OpenAPI documents + uid: fundamentals/openapi/using-openapi-documents + - name: OpenAPI tools + uid: fundamentals/openapi/openapi-tools + - name: Swagger / NSwag + items: + - name: Overview + uid: tutorials/web-api-help-pages-using-swagger + - name: Get started with Swashbuckle + uid: tutorials/get-started-with-swashbuckle + - name: Get started with NSwag + uid: tutorials/get-started-with-nswag - name: Controller-based APIs items: - name: Overview @@ -872,64 +942,12 @@ items: uid: web-api/advanced/analyzers - name: Conventions uid: web-api/advanced/conventions - - name: Handle errors - uid: web-api/handle-errors - name: Test with HttpRepl items: - name: Overview uid: web-api/http-repl - name: Telemetry uid: web-api/http-repl/telemetry - - name: Minimal APIs - items: - - name: Overview - uid: fundamentals/minimal-apis/overview - - name: "Tutorial: Create a minimal API" - uid: tutorials/min-web-api - - name: Minimal APIs quick reference - uid: fundamentals/minimal-apis - - name: WebApplication and WebApplicationBuilder - uid: fundamentals/minimal-apis/webapplication - - name: Route Handlers - uid: fundamentals/minimal-apis/route-handlers - - name: Parameter binding - uid: fundamentals/minimal-apis/parameter-binding - - name: Create responses - uid: fundamentals/minimal-apis/responses - - name: Filters - uid: fundamentals/minimal-apis/min-api-filters - - name: Unit and integration tests - uid: fundamentals/minimal-apis/test-min-api - - name: Middleware - uid: fundamentals/minimal-apis/middleware - - name: Handle errors - uid: fundamentals/minimal-apis/handle-errors - - name: Authentication and authorization - uid: fundamentals/minimal-apis/security - - name: OpenAPI - items: - - name: Overview - uid: fundamentals/openapi/overview - - name: Generate OpenAPI documents - uid: fundamentals/openapi/aspnetcore-openapi - - name: Include OpenAPI metadata - uid: fundamentals/openapi/include-metadata - - name: XML doc comment support - uid: fundamentals/openapi/aspnet-openapi-xml - - name: Customize OpenAPI documents - uid: fundamentals/openapi/customize-openapi - - name: Use OpenAPI documents - uid: fundamentals/openapi/using-openapi-documents - - name: OpenAPI tools - uid: fundamentals/openapi/openapi-tools - - name: Swagger / NSwag - items: - - name: Overview - uid: tutorials/web-api-help-pages-using-swagger - - name: Get started with Swashbuckle - uid: tutorials/get-started-with-swashbuckle - - name: Get started with NSwag - uid: tutorials/get-started-with-nswag - name: Real-time apps displayName: signalr items: @@ -1154,7 +1172,7 @@ items: uid: fundamentals/servers/index - name: HTTP.sys displayName: deploy, publish, server, httpsys - uid: fundamentals/servers/httpsys + uid: fundamentals/servers/httpsys - name: Kestrel items: - name: Overview @@ -1324,7 +1342,7 @@ items: displayName: yarp uid: fundamentals/servers/yarp/websockets - name: Extensibility - items: + items: - name: Overview displayName: yarp uid: fundamentals/servers/yarp/extensibility @@ -1347,7 +1365,7 @@ items: uid: fundamentals/servers/yarp/httpsys-delegation - name: Service Fabric Integration displayName: yarp - uid: fundamentals/servers/yarp/service-fabric-int + uid: fundamentals/servers/yarp/service-fabric-int - name: YARP Kubernetes Ingress Controller displayName: yarp uid: fundamentals/servers/yarp/kubernetes-ingress @@ -1389,6 +1407,8 @@ items: uid: test/loadtests - name: Test middleware uid: test/middleware + - name: .localhost top-level domain + uid: test/localhost-tld - name: Debug items: - name: Debug with Visual Studio @@ -1566,7 +1586,7 @@ items: - name: Inheritance uid: data/ef-mvc/inheritance - name: Advanced topics - uid: data/ef-mvc/advanced + uid: data/ef-mvc/advanced - name: Scaffold a data model with dotnet scaffold in RP uid: data/dotnet-scaffold-rp - name: EF 6 with ASP.NET Core @@ -1764,6 +1784,8 @@ items: href: /azure/active-directory-b2c/enable-authentication-web-api - name: Configure cookie authentication uid: security/authentication/cookie + - name: API endpoint authentication behavior + uid: security/authentication/api-endpoint-auth - name: Configure OIDC web authentication uid: security/authentication/configure-oidc-web-authentication - name: Configure JWT bearer authentication @@ -2123,7 +2145,7 @@ items: uid: migration/fx-to-core/inc/blazor - name: Technology Areas items: - - name: Overview + - name: Overview uid: migration/fx-to-core/areas - name: HttpContext uid: migration/fx-to-core/areas/http-context diff --git a/aspnetcore/tutorials/first-mvc-app/adding-model.md b/aspnetcore/tutorials/first-mvc-app/adding-model.md index 8ba76d45d4dd..83a6d8b9ca71 100644 --- a/aspnetcore/tutorials/first-mvc-app/adding-model.md +++ b/aspnetcore/tutorials/first-mvc-app/adding-model.md @@ -394,7 +394,7 @@ Examine the `Index.cshtml` view and the `Index` method in the Movies controller. [!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/mvcmovie90/Controllers/MoviesController.cs?name=snippet_FirstIndexNoSearch)] -The code returns [problem details](xref:web-api/handle-errors#problem-details-service) if the `Movie` property of the data context is null. +The code returns [problem details](xref:fundamentals/error-handling-api#problem-details-service) if the `Movie` property of the data context is null. When the movies controller was created, scaffolding included the following `@model` statement at the top of the `Index.cshtml` file: diff --git a/aspnetcore/tutorials/first-mvc-app/adding-model/includes/adding-model7.md b/aspnetcore/tutorials/first-mvc-app/adding-model/includes/adding-model7.md index 89cf57ff05a3..f493e61a1bdb 100644 --- a/aspnetcore/tutorials/first-mvc-app/adding-model/includes/adding-model7.md +++ b/aspnetcore/tutorials/first-mvc-app/adding-model/includes/adding-model7.md @@ -460,7 +460,7 @@ Examine the `Index.cshtml` view and the `Index` method in the Movies controller. [!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/MvcMovie70/Controllers/MoviesController.cs?name=snippet_FirstIndexNoSearch)] -The code returns [problem details](xref:web-api/handle-errors#problem-details-service) if the `Movie` property of the data context is null. +The code returns [problem details](xref:fundamentals/error-handling-api#problem-details-service) if the `Movie` property of the data context is null. When the movies controller was created, scaffolding included the following `@model` statement at the top of the `Index.cshtml` file: diff --git a/aspnetcore/tutorials/first-mvc-app/adding-model/includes/adding-model8.md b/aspnetcore/tutorials/first-mvc-app/adding-model/includes/adding-model8.md index 3f8265e5bc46..a5380e0d1db2 100644 --- a/aspnetcore/tutorials/first-mvc-app/adding-model/includes/adding-model8.md +++ b/aspnetcore/tutorials/first-mvc-app/adding-model/includes/adding-model8.md @@ -364,7 +364,7 @@ Examine the `Index.cshtml` view and the `Index` method in the Movies controller. [!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/mvcmovie80/Controllers/MoviesController.cs?name=snippet_FirstIndexNoSearch)] -The code returns [problem details](xref:web-api/handle-errors#problem-details-service) if the `Movie` property of the data context is null. +The code returns [problem details](xref:fundamentals/error-handling-api#problem-details-service) if the `Movie` property of the data context is null. When the movies controller was created, scaffolding included the following `@model` statement at the top of the `Index.cshtml` file: diff --git a/aspnetcore/tutorials/getting-started-with-swashbuckle/includes/getting-started-with-swashbuckle8.md b/aspnetcore/tutorials/getting-started-with-swashbuckle/includes/getting-started-with-swashbuckle8.md index 6c96ab2214ef..19a0ad062a1e 100644 --- a/aspnetcore/tutorials/getting-started-with-swashbuckle/includes/getting-started-with-swashbuckle8.md +++ b/aspnetcore/tutorials/getting-started-with-swashbuckle/includes/getting-started-with-swashbuckle8.md @@ -58,7 +58,7 @@ Add the Swagger generator to the services collection in `Program.cs`: :::code language="csharp" source="~/tutorials/web-api-help-pages-using-swagger/samples/6.x/SwashbuckleSample/Snippets/Program.cs" id="snippet_ServicesDefault" highlight="3,4"::: -The call to shown in the preceding example is required only for [minimal APIs](/aspnet/core/fundamentals/minimal-apis/overview). For more information, see [this StackOverflow post](https://stackoverflow.com/a/71933535). +The call to shown in the preceding example is required only for [minimal APIs](/aspnet/core/fundamentals/apis). For more information, see [this StackOverflow post](https://stackoverflow.com/a/71933535). Enable the middleware for serving the generated JSON document and the Swagger UI, also in `Program.cs`: diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index c3a9fb0cd597..b9ad3f661f0c 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -94,7 +94,7 @@ The `Program.cs` file contains the following code: The preceding code: * Creates a and a with preconfigured defaults. -* Creates an HTTP GET endpoint `/` that returns `Hello World!`: +* Creates an HTTP GET endpoint `/` that returns `Hello World!`. ### Run the app @@ -664,7 +664,7 @@ If you run into a problem you can't resolve, compare your code to the completed ## Next steps * [Configure JSON serialization options](xref:fundamentals/minimal-apis/responses#configure-json-serialization-options). -* Handle errors and exceptions: The [developer exception page](xref:web-api/handle-errors#developer-exception-page) is enabled by default in the development environment for minimal API apps. For information about how to handle errors and exceptions, see [Handle errors in ASP.NET Core APIs](xref:web-api/handle-errors). +* Handle errors and exceptions: The [developer exception page](xref:fundamentals/error-handling-api#developer-exception-page) is enabled by default in the development environment for minimal API apps. For information about how to handle errors and exceptions, see [Handle errors in ASP.NET Core APIs](xref:fundamentals/error-handling-api). * For an example of testing a minimal API app, see [this GitHub sample](https://github.com/dotnet/AspNetCore.Docs.Samples/tree/main/fundamentals/minimal-apis/samples/MinApiTestsSample). * [OpenAPI support in minimal APIs](xref:fundamentals/openapi/aspnetcore-openapi). * [Quickstart: Publish to Azure](/azure/app-service/quickstart-dotnetcore). diff --git a/aspnetcore/tutorials/min-web-api/includes/min-web-api6-7.md b/aspnetcore/tutorials/min-web-api/includes/min-web-api6-7.md index e7f96ddbb72d..96919f0bcd79 100644 --- a/aspnetcore/tutorials/min-web-api/includes/min-web-api6-7.md +++ b/aspnetcore/tutorials/min-web-api/includes/min-web-api6-7.md @@ -441,7 +441,7 @@ If you run into a problem you can't resolve, compare your code to the completed ## Next steps * [Configure JSON serialization options](xref:fundamentals/minimal-apis/responses#configure-json-serialization-options). -* Handle errors and exceptions: The [developer exception page](xref:web-api/handle-errors#developer-exception-page) is enabled by default in the development environment for minimal API apps. For information about how to handle errors and exceptions, see [Handle errors in ASP.NET Core APIs](xref:web-api/handle-errors). +* Handle errors and exceptions: The [developer exception page](xref:fundamentals/error-handling-api#developer-exception-page) is enabled by default in the development environment for minimal API apps. For information about how to handle errors and exceptions, see [Handle errors in ASP.NET Core APIs](xref:fundamentals/error-handling-api). * For an example of testing a minimal API app, see [this GitHub sample](https://github.com/dotnet/AspNetCore.Docs.Samples/tree/main/fundamentals/minimal-apis/samples/MinApiTestsSample). * [OpenAPI support in minimal APIs](xref:fundamentals/openapi/aspnetcore-openapi). * [Quickstart: Publish to Azure](/azure/app-service/quickstart-dotnetcore). diff --git a/aspnetcore/tutorials/min-web-api/includes/min-web-api8.md b/aspnetcore/tutorials/min-web-api/includes/min-web-api8.md index 7c42a3092b0a..b396f23727ba 100644 --- a/aspnetcore/tutorials/min-web-api/includes/min-web-api8.md +++ b/aspnetcore/tutorials/min-web-api/includes/min-web-api8.md @@ -642,7 +642,7 @@ If you run into a problem you can't resolve, compare your code to the completed ## Next steps * [Configure JSON serialization options](xref:fundamentals/minimal-apis/responses#configure-json-serialization-options). -* Handle errors and exceptions: The [developer exception page](xref:web-api/handle-errors#developer-exception-page) is enabled by default in the development environment for minimal API apps. For information about how to handle errors and exceptions, see [Handle errors in ASP.NET Core APIs](xref:web-api/handle-errors). +* Handle errors and exceptions: The [developer exception page](xref:fundamentals/error-handling-api#developer-exception-page) is enabled by default in the development environment for minimal API apps. For information about how to handle errors and exceptions, see [Handle errors in ASP.NET Core APIs](xref:fundamentals/error-handling-api). * For an example of testing a minimal API app, see [this GitHub sample](https://github.com/dotnet/AspNetCore.Docs.Samples/tree/main/fundamentals/minimal-apis/samples/MinApiTestsSample). * [OpenAPI support in minimal APIs](xref:fundamentals/openapi/aspnetcore-openapi). * [Quickstart: Publish to Azure](/azure/app-service/quickstart-dotnetcore). diff --git a/aspnetcore/web-api/handle-errors.md b/aspnetcore/web-api/handle-errors.md deleted file mode 100644 index 71749a798069..000000000000 --- a/aspnetcore/web-api/handle-errors.md +++ /dev/null @@ -1,591 +0,0 @@ ---- -title: Handle errors in ASP.NET Core controller-based web APIs -author: tdykstra -description: Learn about error handling with ASP.NET Core controller-based web APIs. -monikerRange: '>= aspnetcore-3.1' -ms.author: tdykstra -ms.custom: mvc -ms.date: 05/30/2024 -uid: web-api/handle-errors ---- -# Handle errors in ASP.NET Core controller-based web APIs - -[!INCLUDE[](~/includes/not-latest-version.md)] - -:::moniker range=">= aspnetcore-7.0" - -This article describes how to handle errors and customize error handling in controller-based ASP.NET Core web APIs. For information about error handling in minimal APIs, see and . - - - -## Developer Exception Page - -[!INCLUDE [](../includes/developer-exception-page.md)] - -To see the Developer Exception Page: - -* Add the following controller action to a controller-based API. The action throws an exception when the endpoint is requested. - - :::code language="csharp" source="handle-errors/samples/6.x/HandleErrorsSample/Controllers/ErrorsController.cs" id="snippet_Throw"::: - -* Run the app in the [development environment](xref:fundamentals/environments). -* Go to the endpoint defined by the controller action. - -## Exception handler - -In non-development environments, use [Exception Handling Middleware](xref:fundamentals/error-handling) to produce an error payload: - -1. In `Program.cs`, call to add the Exception Handling Middleware: - - :::code language="csharp" source="handle-errors/samples/6.x/HandleErrorsSample/Program.cs" id="snippet_Middleware" highlight="7"::: - -1. Configure a controller action to respond to the `/error` route: - - :::code language="csharp" source="handle-errors/samples/6.x/HandleErrorsSample/Controllers/ErrorsController.cs" id="snippet_HandleError"::: - -The preceding `HandleError` action sends an [RFC 7807](https://tools.ietf.org/html/rfc7807)-compliant payload to the client. - -> [!WARNING] -> Don't mark the error handler action method with HTTP method attributes, such as `HttpGet`. Explicit verbs prevent some requests from reaching the action method. -> -> For web APIs that use [Swagger / OpenAPI](xref:tutorials/web-api-help-pages-using-swagger), mark the error handler action with the [[ApiExplorerSettings]](xref:Microsoft.AspNetCore.Mvc.ApiExplorerSettingsAttribute) attribute and set its property to `true`. This attribute configuration excludes the error handler action from the app's OpenAPI specification: -> -> ```csharp -> [ApiExplorerSettings(IgnoreApi = true)] -> ``` -> -> Allow anonymous access to the method if unauthenticated users should see the error. - -Exception Handling Middleware can also be used in the Development environment to produce a consistent payload format across all environments: - -1. In `Program.cs`, register environment-specific Exception Handling Middleware instances: - - :::code language="csharp" source="handle-errors/samples/6.x/HandleErrorsSample/Snippets/Program.cs" id="snippet_ConsistentEnvironments"::: - - In the preceding code, the middleware is registered with: - - * A route of `/error-development` in the Development environment. - * A route of `/error` in non-Development environments. - - -1. Add controller actions for both the Development and non-Development routes: - - :::code language="csharp" source="handle-errors/samples/6.x/HandleErrorsSample/Controllers/ErrorsController.cs" id="snippet_ConsistentEnvironments"::: - -## Use exceptions to modify the response - -The contents of the response can be modified from outside of the controller using a custom exception and an action filter: - -1. Create a well-known exception type named `HttpResponseException`: - - :::code language="csharp" source="handle-errors/samples/6.x/HandleErrorsSample/Snippets/HttpResponseException.cs" id="snippet_Class"::: - -1. Create an action filter named `HttpResponseExceptionFilter`: - - :::code language="csharp" source="handle-errors/samples/6.x/HandleErrorsSample/Snippets/HttpResponseExceptionFilter.cs" id="snippet_Class"::: - - The preceding filter specifies an `Order` of the maximum integer value minus 10. This `Order` allows other filters to run at the end of the pipeline. - -1. In `Program.cs`, add the action filter to the filters collection: - - :::code language="csharp" source="handle-errors/samples/6.x/HandleErrorsSample/Snippets/Program.cs" id="snippet_AddHttpResponseExceptionFilter"::: - -## Validation failure error response - -For web API controllers, MVC responds with a response type when model validation fails. MVC uses the results of to construct the error response for a validation failure. The following example replaces the default factory with an implementation that also supports formatting responses as XML, in `Program.cs`: - -:::code language="csharp" source="handle-errors/samples/6.x/HandleErrorsSample/Snippets/Program.cs" id="snippet_ConfigureInvalidModelStateResponseFactory"::: - -## Client error response - -An *error result* is defined as a result with an HTTP status code of 400 or higher. For web API controllers, MVC transforms an error result to produce a . - -The automatic creation of a `ProblemDetails` for error status codes is enabled by default, but error responses can be configured in one of the following ways: - -1. Use the [problem details service](#pds7) -1. [Implement ProblemDetailsFactory](#implement-problemdetailsfactory) -1. [Use ApiBehaviorOptions.ClientErrorMapping](#use-apibehavioroptionsclienterrormapping) - -### Default problem details response - -The following `Program.cs` file was generated by the web application templates for API controllers: - -:::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Program.cs" id="snippet_default"::: - -Consider the following controller, which returns when the input is invalid: - -:::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Controllers/ValuesController.cs" id="snippet_1"::: - -A problem details response is generated with the preceding code when any of the following conditions apply: - -* The `/api/values2/divide` endpoint is called with a zero denominator. -* The `/api/values2/squareroot` endpoint is called with a radicand less than zero. - -The default problem details response body has the following `type`, `title`, and `status` values: - -```json -{ - "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1", - "title": "Bad Request", - "status": 400, - "traceId": "00-84c1fd4063c38d9f3900d06e56542d48-85d1d4-00" -} -``` - - - -### Problem details service - -ASP.NET Core supports creating [Problem Details for HTTP APIs](https://www.rfc-editor.org/rfc/rfc9457) using the . For more information, see the [Problem details service](/aspnet/core/fundamentals/error-handling#problem-details). - -The following code configures the app to generate a problem details response for all HTTP client and server error responses that ***don't have body content yet***: - -:::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Program.cs" id="snippet_apishort" highlight="4,8-9,13"::: - -Consider the API controller from the preceding section, which returns when the input is invalid: - -:::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Controllers/ValuesController.cs" id="snippet_1"::: - -A problem details response is generated with the preceding code when any of the following conditions apply: - -* An invalid input is supplied. -* The URI has no matching endpoint. -* An unhandled exception occurs. - -The automatic creation of a `ProblemDetails` for error status codes is disabled when the property is set to `true`: - -:::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Program.cs" id="snippet_disable" highlight="4-7"::: - -Using the preceding code, when an API controller returns `BadRequest`, an [HTTP 400](https://developer.mozilla.org/docs/Web/HTTP/Status/400) response status is returned with no response body. `SuppressMapClientErrors` prevents a `ProblemDetails` response from being created, even when calling `WriteAsync` for an API Controller endpoint. `WriteAsync` is explained later in this article. - -The next section shows how to customize the problem details response body, using , to return a more helpful response. For more customization options, see [Customizing problem details](/aspnet/core/fundamentals/error-handling#cpd7). - -#### Customize problem details with `CustomizeProblemDetails` - -The following code uses to set : - -:::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Program.cs" id="snippet_api_controller" highlight="6"::: - -The updated API controller: - -:::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Controllers/ValuesController.cs" id="snippet" highlight="9-17,27-35"::: - -The following code contains the `MathErrorFeature` and `MathErrorType`, which are used with the preceding sample: - -:::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/MathErrorFeature.cs" ::: - -A problem details response is generated with the preceding code when any of the following conditions apply: - -* The `/divide` endpoint is called with a zero denominator. -* The `/squareroot` endpoint is called with a radicand less than zero. -* The URI has no matching endpoint. - -The problem details response body contains the following when either `squareroot` endpoint is called with a radicand less than zero: - -```json -{ - "type": "https://en.wikipedia.org/wiki/Square_root", - "title": "Bad Input", - "status": 400, - "detail": "Negative or complex numbers are not allowed." -} -``` - -[View or download sample code](https://github.com/dotnet/AspNetCore.Docs.Samples/tree/main/fundamentals/middleware/problem-details-service) - - -### Implement `ProblemDetailsFactory` - -MVC uses to produce all instances of and . This factory is used for: - -* Client error responses -* Validation failure error responses -* and - -To customize the problem details response, register a custom implementation of in `Program.cs`: - -:::code language="csharp" source="handle-errors/samples/6.x/HandleErrorsSample/Snippets/Program.cs" id="snippet_ReplaceProblemDetailsFactory"::: - -### Use `ApiBehaviorOptions.ClientErrorMapping` - -Use the property to configure the contents of the `ProblemDetails` response. For example, the following code in `Program.cs` updates the property for 404 responses: - -:::code language="csharp" source="handle-errors/samples/6.x/HandleErrorsSample/Snippets/Program.cs" id="snippet_ClientErrorMapping"::: - -## Additional resources - -* [How to Use ModelState Validation in ASP.NET Core Web API](https://code-maze.com/aspnetcore-modelstate-validation-web-api/) -* [View or download sample code](https://github.com/dotnet/AspNetCore.Docs.Samples/tree/main/fundamentals/middleware/problem-details-service) -* [Hellang.Middleware.ProblemDetails](https://www.nuget.org/packages/Hellang.Middleware.ProblemDetails/) - -:::moniker-end - -:::moniker range="= aspnetcore-6.0" - -This article describes how to handle errors and customize error handling with ASP.NET Core web APIs. - -## Developer Exception Page - -The [Developer Exception Page](xref:fundamentals/error-handling) shows detailed stack traces for server errors. It uses to capture synchronous and asynchronous exceptions from the HTTP pipeline and to generate error responses. For example, consider the following controller action, which throws an exception: - -:::code language="csharp" source="handle-errors/samples/6.x/HandleErrorsSample/Controllers/ErrorsController.cs" id="snippet_Throw"::: - -When the Developer Exception Page detects an unhandled exception, it generates a default plain-text response similar to the following example: - -```console -HTTP/1.1 500 Internal Server Error -Content-Type: text/plain; charset=utf-8 -Server: Kestrel -Transfer-Encoding: chunked - -System.Exception: Sample exception. - at HandleErrorsSample.Controllers.ErrorsController.Get() in ... - at lambda_method1(Closure , Object , Object[] ) - at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) - at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync() - at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) - at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync() - -... -``` - -If the client requests an HTML-formatted response, the Developer Exception Page generates a response similar to the following example: - -```console -HTTP/1.1 500 Internal Server Error -Content-Type: text/html; charset=utf-8 -Server: Kestrel -Transfer-Encoding: chunked - - - - - - Internal Server Error -