diff --git a/aspnetcore/blazor/security/blazor-web-app-with-entra.md b/aspnetcore/blazor/security/blazor-web-app-with-entra.md index cbf90468b679..0e7d9edd0b4a 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-entra.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-entra.md @@ -99,11 +99,11 @@ Example: ```json "AzureAd": { "CallbackPath": "/signin-oidc", - "ClientId": "41451fa7-82d9-4673-8fa5-69eff5a761fd", + "ClientId": "00001111-aaaa-2222-bbbb-3333cccc4444", "Domain": "contoso.onmicrosoft.com", "Instance": "https://login.microsoftonline.com/", "ResponseType": "code", - "TenantId": "e86c78e2-8bb4-4c41-aefd-918e0565a45e" + "TenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee" }, ``` diff --git a/aspnetcore/blazor/security/blazor-web-app-with-oidc.md b/aspnetcore/blazor/security/blazor-web-app-with-oidc.md index cc8607b339a1..0c56f1b85a9a 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-oidc.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-oidc.md @@ -112,12 +112,12 @@ The following and configuration of and : Many OIDC servers use "`name`" and "`role`" rather than the SOAP/WS-Fed defaults in . When is set to `false`, the handler doesn't perform claims mappings, and the claim names from the JWT are used directly by the app. The following example sets the role claim type to "`roles`," which is appropriate for [Microsoft Entra ID (ME-ID)](https://www.microsoft.com/security/business/microsoft-entra). Consult your identity provider's documentation for more information. -> [!NOTE] -> must be set to `false` for most OIDC providers, which prevents renaming claims. + > [!NOTE] + > must be set to `false` for most OIDC providers, which prevents renaming claims. ```csharp oidcOptions.MapInboundClaims = false; @@ -179,19 +179,19 @@ The following [!NOTE] > A port isn't required for `localhost` addresses when using Microsoft Entra ID. Most other OIDC providers require a correct port. - ```csharp - oidcOptions.CallbackPath = new PathString("{PATH}"); - oidcOptions.SignedOutCallbackPath = new PathString("{PATH}"); - oidcOptions.RemoteSignOutPath = new PathString("{PATH}"); - ``` + ```csharp + oidcOptions.CallbackPath = new PathString("{PATH}"); + oidcOptions.SignedOutCallbackPath = new PathString("{PATH}"); + oidcOptions.RemoteSignOutPath = new PathString("{PATH}"); + ``` - Examples (default values): + Examples (default values): - ```csharp - oidcOptions.CallbackPath = new PathString("/signin-oidc"); - oidcOptions.SignedOutCallbackPath = new PathString("/signout-callback-oidc"); - oidcOptions.RemoteSignOutPath = new PathString("/signout-oidc"); - ``` + ```csharp + oidcOptions.CallbackPath = new PathString("/signin-oidc"); + oidcOptions.SignedOutCallbackPath = new PathString("/signout-callback-oidc"); + oidcOptions.RemoteSignOutPath = new PathString("/signout-oidc"); + ``` * (*Microsoft Azure only with the "common" endpoint*) : Many OIDC providers work with the default issuer validator, but we need to account for the issuer parameterized with the Tenant ID (`{TENANT ID}`) returned by `https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration`. For more information, see [SecurityTokenInvalidIssuerException with OpenID Connect and the Azure AD "common" endpoint (`AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet` #1731)](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/1731). @@ -359,7 +359,7 @@ The following and : Sets the Authority and Client ID for OIDC calls. @@ -386,12 +386,12 @@ The following and configuration of and : Many OIDC servers use "`name`" and "`role`" rather than the SOAP/WS-Fed defaults in . When is set to `false`, the handler doesn't perform claims mappings and the claim names from the JWT are used directly by the app. The following example sets the role claim type to "`roles`," which is appropriate for [Microsoft Entra ID (ME-ID)](https://www.microsoft.com/security/business/microsoft-entra). Consult your identity provider's documentation for more information. -> [!NOTE] -> must be set to `false` for most OIDC providers, which prevents renaming claims. + > [!NOTE] + > must be set to `false` for most OIDC providers, which prevents renaming claims. ```csharp oidcOptions.MapInboundClaims = false; @@ -453,19 +453,19 @@ The following [!NOTE] > A port isn't required for `localhost` addresses. - ```csharp - oidcOptions.CallbackPath = new PathString("{PATH}"); - oidcOptions.SignedOutCallbackPath = new PathString("{PATH}"); - oidcOptions.RemoteSignOutPath = new PathString("{PATH}"); - ``` + ```csharp + oidcOptions.CallbackPath = new PathString("{PATH}"); + oidcOptions.SignedOutCallbackPath = new PathString("{PATH}"); + oidcOptions.RemoteSignOutPath = new PathString("{PATH}"); + ``` - Examples (default values): + Examples (default values): - ```csharp - oidcOptions.CallbackPath = new PathString("/signin-oidc"); - oidcOptions.SignedOutCallbackPath = new PathString("/signout-callback-oidc"); - oidcOptions.RemoteSignOutPath = new PathString("/signout-oidc"); - ``` + ```csharp + oidcOptions.CallbackPath = new PathString("/signin-oidc"); + oidcOptions.SignedOutCallbackPath = new PathString("/signout-callback-oidc"); + oidcOptions.RemoteSignOutPath = new PathString("/signout-oidc"); + ``` * (*Microsoft Azure only with the "common" endpoint*) : Many OIDC providers work with the default issuer validator, but we need to account for the issuer parameterized with the Tenant ID (`{TENANT ID}`) returned by `https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration`. For more information, see [SecurityTokenInvalidIssuerException with OpenID Connect and the Azure AD "common" endpoint (`AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet` #1731)](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/1731). @@ -533,20 +533,20 @@ Configure the project in the : Sets the Authority for making OpenID Connect calls. Match the value to the Authority configured for the OIDC handler in `BlazorWebAppOidc/Program.cs`: @@ -557,7 +557,7 @@ Configure the project in the [!NOTE] > Supplying the port number for a `localhost` AAD B2C redirect URI isn't required. For more information, see [Redirect URI (reply URL) restrictions and limitations: Localhost exceptions (Entra documentation)](/entra/identity-platform/reply-url#localhost-exceptions). -Record the *Client app* Application (client) ID (for example, `4369008b-21fa-427c-abaa-9b53bf58e538`). +Record the *Client app* Application (client) ID (for example, `11112222-bbbb-3333-cccc-4444dddd5555`). In **Authentication** > **Platform configurations** > **Single-page application**: @@ -116,10 +116,10 @@ dotnet new blazorwasm -au IndividualB2C --aad-b2c-instance "{AAD B2C INSTANCE}" | --- | --- | --- | | `{AAD B2C INSTANCE}` | Instance | `https://contoso.b2clogin.com/` (includes the trailing slash) | | `{PROJECT NAME}` | — | `BlazorSample` | -| `{CLIENT APP CLIENT ID}` | Application (client) ID for the **:::no-loc text="Client":::** app | `4369008b-21fa-427c-abaa-9b53bf58e538` | +| `{CLIENT APP CLIENT ID}` | Application (client) ID for the **:::no-loc text="Client":::** app | `11112222-bbbb-3333-cccc-4444dddd5555` | | `{DEFAULT SCOPE}` | Scope name | `API.Access` | -| `{SERVER API APP CLIENT ID}` | Application (client) ID for the **:::no-loc text="Server":::** app | `41451fa7-82d9-4673-8fa5-69eff5a761fd` | -| `{SERVER API APP ID URI GUID}` | Application ID URI GUID | `41451fa7-82d9-4673-8fa5-69eff5a761fd` (GUID ONLY, matches the `{SERVER API APP CLIENT ID}`) | +| `{SERVER API APP CLIENT ID}` | Application (client) ID for the **:::no-loc text="Server":::** app | `00001111-aaaa-2222-bbbb-3333cccc4444` | +| `{SERVER API APP ID URI GUID}` | Application ID URI GUID | `00001111-aaaa-2222-bbbb-3333cccc4444` (GUID ONLY, matches the `{SERVER API APP CLIENT ID}`) | | `{SIGN UP OR SIGN IN POLICY}` | Sign-up/sign-in user flow | `B2C_1_signupsignin1` | | `{TENANT DOMAIN}` | Primary/Publisher/Tenant domain | `contoso.onmicrosoft.com` | @@ -185,7 +185,7 @@ Example: { "AzureAdB2C": { "Instance": "https://contoso.b2clogin.com/", - "ClientId": "41451fa7-82d9-4673-8fa5-69eff5a761fd", + "ClientId": "00001111-aaaa-2222-bbbb-3333cccc4444", "Domain": "contoso.onmicrosoft.com", "Scopes": "API.Access", "SignUpSignInPolicyId": "B2C_1_signupsignin1", @@ -273,7 +273,7 @@ Example: { "AzureAdB2C": { "Authority": "https://contoso.b2clogin.com/contoso.onmicrosoft.com/B2C_1_signupsignin1", - "ClientId": "4369008b-21fa-427c-abaa-9b53bf58e538", + "ClientId": "11112222-bbbb-3333-cccc-4444dddd5555", "ValidateAuthority": false } } @@ -322,7 +322,7 @@ builder.Services.AddMsalAuthentication(options => }); ``` -The `{SCOPE URI}` is the default access token scope (for example, `https://contoso.onmicrosoft.com/41451fa7-82d9-4673-8fa5-69eff5a761fd/API.Access` or the custom URI that you configured in the Azure portal). +The `{SCOPE URI}` is the default access token scope (for example, `https://contoso.onmicrosoft.com/00001111-aaaa-2222-bbbb-3333cccc4444/API.Access` or the custom URI that you configured in the Azure portal). The method accepts a callback to configure the parameters required to authenticate an app. The values required for configuring the app can be obtained from the Azure Portal AAD configuration when you register the app. diff --git a/aspnetcore/blazor/security/webassembly/hosted-with-microsoft-entra-id.md b/aspnetcore/blazor/security/webassembly/hosted-with-microsoft-entra-id.md index 63c3723aae91..2f865310c285 100644 --- a/aspnetcore/blazor/security/webassembly/hosted-with-microsoft-entra-id.md +++ b/aspnetcore/blazor/security/webassembly/hosted-with-microsoft-entra-id.md @@ -47,8 +47,8 @@ Register an ME-ID app for the *Server API app*: Record the following information: -* *Server API app* Application (client) ID (for example, `41451fa7-82d9-4673-8fa5-69eff5a761fd`) -* Directory (tenant) ID (for example, `e86c78e2-8bb4-4c41-aefd-918e0565a45e`) +* *Server API app* Application (client) ID (for example, `00001111-aaaa-2222-bbbb-3333cccc4444`) +* Directory (tenant) ID (for example, `aaaabbbb-0000-cccc-1111-dddd2222eeee`) * ME-ID Primary/Publisher/Tenant domain (for example, `contoso.onmicrosoft.com`): The domain is available as the **Publisher domain** in the **Branding** blade of the Azure portal for the registered app. In **API permissions**, remove the **Microsoft Graph** > **User.Read** permission, as the server API app doesn't require additional API access for merely signing in users and calling server API endpoints. @@ -66,7 +66,7 @@ In **Expose an API**: Record the following information: -* App ID URI GUID (for example, record `41451fa7-82d9-4673-8fa5-69eff5a761fd` from the App ID URI of `api://41451fa7-82d9-4673-8fa5-69eff5a761fd`) +* App ID URI GUID (for example, record `00001111-aaaa-2222-bbbb-3333cccc4444` from the App ID URI of `api://00001111-aaaa-2222-bbbb-3333cccc4444`) * Scope name (for example, `API.Access`) > [!IMPORTANT] @@ -86,7 +86,7 @@ Register an ME-ID app for the *Client app*: > [!NOTE] > Supplying the port number for a `localhost` ME-ID redirect URI isn't required. For more information, see [Redirect URI (reply URL) restrictions and limitations: Localhost exceptions (Entra documentation)](/entra/identity-platform/reply-url#localhost-exceptions). -Record the **:::no-loc text="Client":::** app Application (client) ID (for example, `4369008b-21fa-427c-abaa-9b53bf58e538`). +Record the **:::no-loc text="Client":::** app Application (client) ID (for example, `11112222-bbbb-3333-cccc-4444dddd5555`). In **Authentication** > **Platform configurations** > **Single-page application**: @@ -121,12 +121,12 @@ dotnet new blazorwasm -au SingleOrg --api-client-id "{SERVER API APP CLIENT ID}" | Placeholder | Azure portal name | Example | | --- | --- | --- | | `{PROJECT NAME}` | — | `BlazorSample` | -| `{CLIENT APP CLIENT ID}` | Application (client) ID for the **:::no-loc text="Client":::** app | `4369008b-21fa-427c-abaa-9b53bf58e538` | +| `{CLIENT APP CLIENT ID}` | Application (client) ID for the **:::no-loc text="Client":::** app | `11112222-bbbb-3333-cccc-4444dddd5555` | | `{DEFAULT SCOPE}` | Scope name | `API.Access` | -| `{SERVER API APP CLIENT ID}` | Application (client) ID for the *Server API app* | `41451fa7-82d9-4673-8fa5-69eff5a761fd` | -| `{SERVER API APP ID URI GUID}` | Application ID URI GUID | `41451fa7-82d9-4673-8fa5-69eff5a761fd` (GUID ONLY, matches the `{SERVER API APP CLIENT ID}`) | +| `{SERVER API APP CLIENT ID}` | Application (client) ID for the *Server API app* | `00001111-aaaa-2222-bbbb-3333cccc4444` | +| `{SERVER API APP ID URI GUID}` | Application ID URI GUID | `00001111-aaaa-2222-bbbb-3333cccc4444` (GUID ONLY, matches the `{SERVER API APP CLIENT ID}`) | | `{TENANT DOMAIN}` | Primary/Publisher/Tenant domain | `contoso.onmicrosoft.com` | -| `{TENANT ID}` | Directory (tenant) ID | `e86c78e2-8bb4-4c41-aefd-918e0565a45e` | +| `{TENANT ID}` | Directory (tenant) ID | `aaaabbbb-0000-cccc-1111-dddd2222eeee` | The output location specified with the `-o|--output` option creates a project folder if it doesn't exist and becomes part of the project's name. **Avoid using dashes (`-`) in the app name that break the formation of the OIDC app identifier (see the earlier WARNING).** @@ -191,8 +191,8 @@ Example: "AzureAd": { "Instance": "https://login.microsoftonline.com/", "Domain": "contoso.onmicrosoft.com", - "TenantId": "e86c78e2-8bb4-4c41-aefd-918e0565a45e", - "ClientId": "41451fa7-82d9-4673-8fa5-69eff5a761fd", + "TenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee", + "ClientId": "00001111-aaaa-2222-bbbb-3333cccc4444", "CallbackPath": "/signin-oidc", "Scopes": "API.Access" } @@ -281,7 +281,7 @@ Example: { "AzureAd": { "Authority": "https://login.microsoftonline.com/e86c78e2-...-918e0565a45e", - "ClientId": "4369008b-21fa-427c-abaa-9b53bf58e538", + "ClientId": "11112222-bbbb-3333-cccc-4444dddd5555", "ValidateAuthority": true } } @@ -364,7 +364,7 @@ Example default access token scope: ```csharp options.ProviderOptions.DefaultAccessTokenScopes.Add( - "api://41451fa7-82d9-4673-8fa5-69eff5a761fd/API.Access"); + "api://00001111-aaaa-2222-bbbb-3333cccc4444/API.Access"); ``` For more information, see the following sections of the *Additional scenarios* article: @@ -448,7 +448,7 @@ Instead of the App ID URI matching the format `api://{SERVER API APP CLIENT ID O Example: ```json - "Audience": "https://contoso.onmicrosoft.com/41451fa7-82d9-4673-8fa5-69eff5a761fd" + "Audience": "https://contoso.onmicrosoft.com/00001111-aaaa-2222-bbbb-3333cccc4444" ``` * In the `Program` file of the **`Client`** app, set the audience of the scope (App ID URI) to match the server API app's audience: @@ -467,7 +467,7 @@ Instead of the App ID URI matching the format `api://{SERVER API APP CLIENT ID O .Add("https://contoso.onmicrosoft.com/41451fa7-82d9-4673-8fa5-69eff5a761fd/API.Access"); ``` - In the preceding scope, the App ID URI/audience is the `https://contoso.onmicrosoft.com/41451fa7-82d9-4673-8fa5-69eff5a761fd` portion of the value, which doesn't include a trailing slash (`/`) and doesn't include the scope name (`API.Access`). + In the preceding scope, the App ID URI/audience is the `https://contoso.onmicrosoft.com/00001111-aaaa-2222-bbbb-3333cccc4444` portion of the value, which doesn't include a trailing slash (`/`) and doesn't include the scope name (`API.Access`). ## Use of a custom App ID URI diff --git a/aspnetcore/blazor/security/webassembly/standalone-with-azure-active-directory-b2c.md b/aspnetcore/blazor/security/webassembly/standalone-with-azure-active-directory-b2c.md index fa12f06151bc..3c85f04c78c0 100644 --- a/aspnetcore/blazor/security/webassembly/standalone-with-azure-active-directory-b2c.md +++ b/aspnetcore/blazor/security/webassembly/standalone-with-azure-active-directory-b2c.md @@ -47,7 +47,7 @@ Register an AAD B2C app: Record the following information: -* Application (client) ID (for example, `41451fa7-82d9-4673-8fa5-69eff5a761fd`). +* Application (client) ID (for example, `00001111-aaaa-2222-bbbb-3333cccc4444`). * AAD B2C instance (for example, `https://contoso.b2clogin.com/`, which includes the trailing slash): The instance is the scheme and host of an Azure B2C app registration, which can be found by opening the **Endpoints** window from the **App registrations** page in the Azure portal. * AAD B2C Primary/Publisher/Tenant domain (for example, `contoso.onmicrosoft.com`): The domain is available as the **Publisher domain** in the **Branding** blade of the Azure portal for the registered app. @@ -78,7 +78,7 @@ dotnet new blazorwasm -au IndividualB2C --aad-b2c-instance "{AAD B2C INSTANCE}" | ----------------------------- | ------------------------------- | ------------------------------------------------------------- | | `{AAD B2C INSTANCE}` | Instance | `https://contoso.b2clogin.com/` (includes the trailing slash) | | `{PROJECT NAME}` | — | `BlazorSample` | -| `{CLIENT ID}` | Application (client) ID | `41451fa7-82d9-4673-8fa5-69eff5a761fd` | +| `{CLIENT ID}` | Application (client) ID | `00001111-aaaa-2222-bbbb-3333cccc4444` | | `{SIGN UP OR SIGN IN POLICY}` | Sign-up/sign-in user flow | `B2C_1_signupsignin1` | | `{TENANT DOMAIN}` | Primary/Publisher/Tenant domain | `contoso.onmicrosoft.com` | @@ -152,7 +152,7 @@ Example: { "AzureAdB2C": { "Authority": "https://contoso.b2clogin.com/contoso.onmicrosoft.com/B2C_1_signupsignin1", - "ClientId": "41451fa7-82d9-4673-8fa5-69eff5a761fd", + "ClientId": "00001111-aaaa-2222-bbbb-3333cccc4444", "ValidateAuthority": false } } diff --git a/aspnetcore/blazor/security/webassembly/standalone-with-microsoft-accounts.md b/aspnetcore/blazor/security/webassembly/standalone-with-microsoft-accounts.md index 03408313a017..8cb0ad193abd 100644 --- a/aspnetcore/blazor/security/webassembly/standalone-with-microsoft-accounts.md +++ b/aspnetcore/blazor/security/webassembly/standalone-with-microsoft-accounts.md @@ -43,7 +43,7 @@ Register an ME-ID app: > [!NOTE] > Supplying the port number for a `localhost` ME-ID redirect URI isn't required. For more information, see [Redirect URI (reply URL) restrictions and limitations: Localhost exceptions (Entra documentation)](/entra/identity-platform/reply-url#localhost-exceptions). -Record the Application (client) ID (for example, `41451fa7-82d9-4673-8fa5-69eff5a761fd`). +Record the Application (client) ID (for example, `00001111-aaaa-2222-bbbb-3333cccc4444`). In **Authentication** > **Platform configurations** > **Single-page application**: @@ -63,7 +63,7 @@ dotnet new blazorwasm -au SingleOrg --client-id "{CLIENT ID}" --tenant-id "commo | Placeholder | Azure portal name | Example | | ---------------- | ----------------------- | -------------------------------------- | | `{PROJECT NAME}` | — | `BlazorSample` | -| `{CLIENT ID}` | Application (client) ID | `41451fa7-82d9-4673-8fa5-69eff5a761fd` | +| `{CLIENT ID}` | Application (client) ID | `00001111-aaaa-2222-bbbb-3333cccc4444` | The output location specified with the `-o|--output` option creates a project folder if it doesn't exist and becomes part of the project's name. @@ -128,7 +128,7 @@ Example: { "AzureAd": { "Authority": "https://login.microsoftonline.com/common", - "ClientId": "41451fa7-82d9-4673-8fa5-69eff5a761fd", + "ClientId": "00001111-aaaa-2222-bbbb-3333cccc4444", "ValidateAuthority": true } } diff --git a/aspnetcore/blazor/security/webassembly/standalone-with-microsoft-entra-id.md b/aspnetcore/blazor/security/webassembly/standalone-with-microsoft-entra-id.md index 71af7bf83679..4d13b87e8a38 100644 --- a/aspnetcore/blazor/security/webassembly/standalone-with-microsoft-entra-id.md +++ b/aspnetcore/blazor/security/webassembly/standalone-with-microsoft-entra-id.md @@ -45,8 +45,8 @@ Register an ME-ID app: Record the following information: -* Application (client) ID (for example, `41451fa7-82d9-4673-8fa5-69eff5a761fd`) -* Directory (tenant) ID (for example, `e86c78e2-8bb4-4c41-aefd-918e0565a45e`) +* Application (client) ID (for example, `00001111-aaaa-2222-bbbb-3333cccc4444`) +* Directory (tenant) ID (for example, `aaaabbbb-0000-cccc-1111-dddd2222eeee`) In **Authentication** > **Platform configurations** > **Single-page application**: @@ -66,8 +66,8 @@ dotnet new blazorwasm -au SingleOrg --client-id "{CLIENT ID}" -o {PROJECT NAME} | Placeholder | Azure portal name | Example | | ---------------- | ----------------------- | -------------------------------------- | | `{PROJECT NAME}` | — | `BlazorSample` | -| `{CLIENT ID}` | Application (client) ID | `41451fa7-82d9-4673-8fa5-69eff5a761fd` | -| `{TENANT ID}` | Directory (tenant) ID | `e86c78e2-8bb4-4c41-aefd-918e0565a45e` | +| `{CLIENT ID}` | Application (client) ID | `00001111-aaaa-2222-bbbb-3333cccc4444` | +| `{TENANT ID}` | Directory (tenant) ID | `aaaabbbb-0000-cccc-1111-dddd2222eeee` | The output location specified with the `-o|--output` option creates a project folder if it doesn't exist and becomes part of the project's name. @@ -132,7 +132,7 @@ Example: { "AzureAd": { "Authority": "https://login.microsoftonline.com/e86c78e2-...-918e0565a45e", - "ClientId": "41451fa7-82d9-4673-8fa5-69eff5a761fd", + "ClientId": "00001111-aaaa-2222-bbbb-3333cccc4444", "ValidateAuthority": true } } diff --git a/aspnetcore/fundamentals/openapi/aspnetcore-openapi.md b/aspnetcore/fundamentals/openapi/aspnetcore-openapi.md index a8d7e3aaf68c..5ace430d8c73 100644 --- a/aspnetcore/fundamentals/openapi/aspnetcore-openapi.md +++ b/aspnetcore/fundamentals/openapi/aspnetcore-openapi.md @@ -76,23 +76,23 @@ Launch the app and navigate to `https://localhost:/openapi/v1.json` to vie ### Including OpenAPI metadata for endpoints ASP.NET collects metadata from the web app's endpoints and uses it to generate an OpenAPI document. -In controller-based apps, metadata is collected from attributes like `[EndpointDescription]`, `[HttpPost]`, -and `[Produces]`. +In controller-based apps, metadata is collected from attributes like [`[EndpointDescription]`](xref:Microsoft.AspNetCore.Http.EndpointDescriptionAttribute), [`[HttpPost]`](xref:Microsoft.AspNetCore.Mvc.HttpPostAttribute), +and [`[Produces]`](xref:Microsoft.AspNetCore.Mvc.ProducesAttribute). In minimal APIs, metadata can be collected from attributes, but may also be set by using extension methods -and other strategies, such as returning `TypedResults` from route handlers. +and other strategies, such as returning [`TypedResults`](xref:Microsoft.AspNetCore.Http.TypedResults) from route handlers. The following table provides an overview of the metadata collected and the strategies for setting it. | Metadata | Attribute | Extension method | Other strategies | | --- | --- | --- | -| summary | `[EndpointSummary]` | `WithSummary` | | -| description | `[EndpointDescription]` | `WithDescription` | | -| tags | `[Tags]` | `WithTags` | | -| operationId | `[EndpointName]` | `WithName` | | -| parameters | `[FromQuery]`, `[FromRoute]`, `[FromHeader]`, `[FromForm]` | | -| parameter description | `[Description]` | | | -| requestBody | `[FromBody]` | `Accepts` | | -| responses | `[Produces]`, `[ProducesProblem]` | `Produces`, `ProducesProblem` | `TypedResults` | -| Excluding endpoints | `[ExcludeFromDescription]` | `ExcludeFromDescription` | | +| summary | [`[EndpointSummary]`](xref:Microsoft.AspNetCore.Http.EndpointSummaryAttribute) | [`WithSummary`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.WithSummary%2A) | | +| description | [`[EndpointDescription]`](xref:Microsoft.AspNetCore.Http.EndpointDescriptionAttribute) | [`WithDescription`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.WithDescription%2A) | | +| tags | [`[Tags]`](xref:Microsoft.AspNetCore.Http.TagsAttribute) | [`WithTags`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.WithTags%2A) | | +| operationId | [`[EndpointName]`](xref:Microsoft.AspNetCore.Routing.EndpointNameAttribute) | [`WithName`](xref:Microsoft.AspNetCore.Builder.RoutingEndpointConventionBuilderExtensions.WithName%2A) | | +| parameters | [`[FromQuery]`](xref:Microsoft.AspNetCore.Mvc.FromQueryAttribute), [`[FromRoute]`](xref:Microsoft.AspNetCore.Mvc.FromRouteAttribute), [`[FromHeader]`](xref:Microsoft.AspNetCore.Mvc.FromHeaderAttribute), [`[FromForm]`](xref:Microsoft.AspNetCore.Mvc.FromFormAttribute) | | +| parameter description | [`[EndpointDescription]`](xref:Microsoft.AspNetCore.Http.EndpointDescriptionAttribute) | | | +| requestBody | [`[FromBody]`](xref:Microsoft.AspNetCore.Mvc.FromBodyAttribute) | [`Accepts`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.Accepts%2A) | | +| responses | [`[Produces]`](xref:Microsoft.AspNetCore.Mvc.ProducesAttribute) | [`Produces`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.Produces%2A), [`ProducesProblem`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.ProducesProblem%2A) | [`TypedResults`](xref:Microsoft.AspNetCore.Http.TypedResults) | +| Excluding endpoints | [`[ExcludeFromDescription]`](xref:Microsoft.AspNetCore.Routing.ExcludeFromDescriptionAttribute), [`[ApiExplorerSettings]`](xref:Microsoft.AspNetCore.Mvc.ApiExplorerSettingsAttribute) | [`ExcludeFromDescription`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.ExcludeFromDescription%2A) | | ASP.NET Core does not collect metadata from XML doc comments. @@ -100,13 +100,8 @@ The following sections demonstrate how to include metadata in an app to customiz #### Summary and description -The endpoint summary and description can be set using the `[EndpointSummary]` and `[EndpointDescription]` attributes, -or in minimal APIs, using the `WithSummary` and `WithDescription` extension methods. - -* `[EndpointSummary]`: -* `[EndpointDescription]`: -* `WithSummary`: -* `WithDescription`: +The endpoint summary and description can be set using the [`[EndpointSummary]`](xref:Microsoft.AspNetCore.Http.EndpointSummaryAttribute) and [`[EndpointDescription]`](xref:Microsoft.AspNetCore.Http.EndpointDescriptionAttribute) attributes, +or in minimal APIs, using the [`WithSummary`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.WithSummary%2A) and [`WithDescription`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.WithDescription%2A) extension methods. ##### [Minimal APIs](#tab/minimal-apis) @@ -143,15 +138,11 @@ The following sample demonstrates how to set summaries and descriptions. #### tags OpenAPI supports specifying tags on each endpoint as a form of categorization. -In controller-based apps, the controller name is automatically added as a tag on each of its endpoints, -but this can be overridden using the `[Tags]` attribute. -In minimal APIs, tags can be set using either the `[Tags]` attribute or the `WithTags` extension method. - -* `[Tags]`: -* `WithTags`: ##### [Minimal APIs](#tab/minimal-apis) +In minimal APIs, tags can be set using either the [`[Tags]`](xref:Microsoft.AspNetCore.Http.TagsAttribute) attribute or the [`WithTags`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.WithTags%2A) extension method. + The following sample demonstrates the different strategies for setting tags. ```csharp @@ -165,6 +156,8 @@ app.MapGet("/attributes", ##### [Controllers](#tab/controllers) +In controller-based apps, the controller name is automatically added as a tag on each of its endpoints, but this can be overridden using the [`[Tags]`](xref:Microsoft.AspNetCore.Http.TagsAttribute) attribute. + The following sample demonstrates how to set tags. ```csharp @@ -180,14 +173,11 @@ The following sample demonstrates how to set tags. #### operationId OpenAPI supports an operationId on each endpoint as a unique identifier or name for the operation. -In controller-based apps, the operationId can be set using the `[EndpointName]` attribute. -In minimal APIs, the operationId can be set using either the `[EndpointName]` attribute or the `WithName` extension method. - -* `[EndpointName]`: -* `WithName`: ##### [Minimal APIs](#tab/minimal-apis) +In minimal APIs, the operationId can be set using either the [`[EndpointName]`](xref:Microsoft.AspNetCore.Routing.EndpointNameAttribute) attribute or the [`WithName`](xref:Microsoft.AspNetCore.Builder.RoutingEndpointConventionBuilderExtensions.WithName%2A) extension method. + The following sample demonstrates the different strategies for setting the operationId. ```csharp @@ -201,6 +191,8 @@ app.MapGet("/attributes", ##### [Controllers](#tab/controllers) +In controller-based apps, the operationId can be set using the [`[EndpointName]`](xref:Microsoft.AspNetCore.Routing.EndpointNameAttribute) attribute. + The following sample demonstrates how to set the operationId. ```csharp @@ -219,9 +211,7 @@ OpenAPI supports annotating path, query string, header, and cookie parameters th The framework infers the types for request parameters automatically based on the signature of the route handler. -The `[Description]` attribute can be used to provide a description for a parameter. - -* [`Description`](/dotnet/api/system.componentmodel.descriptionattribute) +The [`[EndpointDescription]`](xref:Microsoft.AspNetCore.Http.EndpointDescriptionAttribute) attribute can be used to provide a description for a parameter. ##### [Minimal APIs](#tab/minimal-apis) @@ -249,7 +239,7 @@ The following sample demonstrates how to set a description for a parameter. -To define the type of inputs transmitted as the request body, configure the properties by using the extension method to define the object type and content type that are expected by the request handler. In the following example, the endpoint accepts a `Todo` object in the request body with an expected content-type of `application/xml`. +To define the type of inputs transmitted as the request body, configure the properties by using the [`Accepts`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.Accepts%2A) extension method to define the object type and content type that are expected by the request handler. In the following example, the endpoint accepts a `Todo` object in the request body with an expected content-type of `application/xml`. ```csharp app.MapPost("/todos/{id}", (int id, Todo todo) => ...) @@ -259,7 +249,7 @@ app.MapPost("/todos/{id}", (int id, Todo todo) => ...) -In addition to the extension method, a parameter type can describe its own annotation by implementing the interface. For example, the following `Todo` type adds an annotation that requires a request body with an `application/xml` content-type. +In addition to the [`Accepts`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.Accepts%2A) extension method, a parameter type can describe its own annotation by implementing the [`IEndpointParameterMetadataProvider`](xref:Microsoft.AspNetCore.Http.Metadata.IEndpointParameterMetadataProvider) interface. For example, the following `Todo` type adds an annotation that requires a request body with an `application/xml` content-type. ```csharp public class Todo : IEndpointParameterMetadataProvider @@ -275,7 +265,7 @@ When no explicit annotation is provided, the framework attempts to determine the * Request body parameters that are read from a form via the [`[FromForm]`](xref:Microsoft.AspNetCore.Mvc.FromFormAttribute) attribute are described with the `multipart/form-data` content-type. * All other request body parameters are described with the `application/json` content-type. -* The request body is treated as optional if it's nullable or if the property is set on the [`FromBody`](xref:Microsoft.AspNetCore.Mvc.FromBodyAttribute) attribute. +* The request body is treated as optional if it's nullable or if the [`AllowEmpty`](xref:Microsoft.AspNetCore.Http.Metadata.IFromBodyMetadata.AllowEmpty) property is set on the [`[FromBody]`](xref:Microsoft.AspNetCore.Mvc.FromBodyAttribute) attribute. #### Describe response types @@ -287,28 +277,28 @@ The specific mechanisms for setting response metadata depend on the type of app In Minimal API apps, ASP.NET Core can extract the response metadata added by extension methods on the endpoint, attributes on the route handler, and the return type of the route handler. -* The extension method can be used on the endpoint to specify the status code, the type of the response body, and content type(s) of a response from an endpoint. -* The or attribute can be used to specify the type of the response body. -* A route handler can be used to return a type that implements to specify the type and content-type(s) of the response body. -* The extension method on the endpoint can be used to specify the status code and content-type(s) of an error response. +* The [`Produces`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.Produces%2A) extension method can be used on the endpoint to specify the status code, the type of the response body, and content type(s) of a response from an endpoint. +* The [`[ProducesResponseType]`](xref:Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute) or [`ProducesResponseTypeAttribute`](xref:Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute%601) attribute can be used to specify the type of the response body. +* A route handler can be used to return a type that implements [`IEndpointMetadataProvider`](xref:Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider) to specify the type and content-type(s) of the response body. +* The [`ProducesProblem`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.ProducesProblem%2A) extension method on the endpoint can be used to specify the status code and content-type(s) of an error response. -Note that the and extension methods are supported on both and on . This allows, for example, a common set of error responses to be defined for all operations in a group. +Note that the [`Produces`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.Produces%2A) and [`ProducesProblem`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.ProducesProblem%2A) extension methods are supported on both [`RouteHandlerBuilder`](xref:Microsoft.AspNetCore.Builder.RouteHandlerBuilder) and on [`RouteGroupBuilder`](xref:Microsoft.AspNetCore.Routing.RouteGroupBuilder). This allows, for example, a common set of error responses to be defined for all operations in a group. When not specified by one of the preceding strategies, the: * Status code for the response defaults to 200. -* Schema for the response body can be inferred from the implicit or explicit return type of the endpoint method, for example, from `T` in ; otherwise, it's considered to be unspecified. +* Schema for the response body can be inferred from the implicit or explicit return type of the endpoint method, for example, from `T` in [`Task`](xref:System.Threading.Tasks.Task%601); otherwise, it's considered to be unspecified. * Content-type for the specified or inferred response body is "application/json". -In Minimal APIs, the extension method and the attribute only set the response metadata for the endpoint. They do not modify or constrain the behavior of the endpoint, which may return a different status code or response body type than specified by the metadata, and the content-type is determined by the return type of the route handler method, irrespective of any content-type specified in attributes or extension methods. +In Minimal APIs, the [`Produces`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.Produces%2A) extension method and the [`[ProducesResponseType]`](xref:Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute) attribute only set the response metadata for the endpoint. They do not modify or constrain the behavior of the endpoint, which may return a different status code or response body type than specified by the metadata, and the content-type is determined by the return type of the route handler method, irrespective of any content-type specified in attributes or extension methods. -The extension method can specify an endpoint's response type, with a default status code of 200 and a default content type of `application/json`. The following example illustrates this: +The [`Produces`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.Produces%2A) extension method can specify an endpoint's response type, with a default status code of 200 and a default content type of `application/json`. The following example illustrates this: ```csharp app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync()) .Produces>(); ``` -The can be used to add response metadata to an endpoint. Note that the attribute is applied to the route handler method, not the method invocation to create the route, as shown in the following example: +The [`[ProducesResponseType]`](xref:Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute) can be used to add response metadata to an endpoint. Note that the attribute is applied to the route handler method, not the method invocation to create the route, as shown in the following example: ```csharp app.MapGet("/todos", @@ -316,7 +306,7 @@ app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync()); ``` -Using in the implementation of an endpoint's route handler automatically includes the response type metadata for the endpoint. For example, the following code automatically annotates the endpoint with a response under the `200` status code with an `application/json` content type. +Using [`TypedResults`](xref:Microsoft.AspNetCore.Http.TypedResults) in the implementation of an endpoint's route handler automatically includes the response type metadata for the endpoint. For example, the following code automatically annotates the endpoint with a response under the `200` status code with an `application/json` content type. ```csharp app.MapGet("/todos", async (TodoDb db) => @@ -326,7 +316,7 @@ app.MapGet("/todos", async (TodoDb db) => }); ``` -Only return types that implement create a `responses` entry in the OpenAPI document. The following is a partial list of some of the helper methods that produce a `responses` entry: +Only return types that implement [`IEndpointMetadataProvider`](xref:Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider) create a `responses` entry in the OpenAPI document. The following is a partial list of some of the [`TypedResults`](xref:Microsoft.AspNetCore.Http.TypedResults) helper methods that produce a `responses` entry: | TypedResults helper method | status code | | -------------------------- | ----------- | @@ -350,9 +340,9 @@ A class can be implemented to set the endpoint metadata and return it from the r When setting the response type for endpoints that may return a ProblemDetails response, the following can be used to add the appropriate response metadata for the endpoint: -* -* extension method. -* with a status code in the (400-499) range. +* [`ProducesProblem`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.ProducesProblem%2A) +* [`ProducesValidationProblem`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.ProducesValidationProblem%2A) extension method. +* [`TypedResults`](xref:Microsoft.AspNetCore.Http.TypedResults) 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 . @@ -360,15 +350,15 @@ For more information on how to configure a Minimal API app to return ProblemDeta If an endpoint can return different response types in different scenarios, you can provide metadata in the following ways: -* Call the extension method multiple times, as shown in the following example: +* Call the [`Produces`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.Produces%2A) extension method multiple times, as shown in the following example: [!code-csharp[](~/fundamentals/minimal-apis/samples/todo/Program.cs?name=snippet_getCustom)] -* Use [`Results`](xref:Microsoft.AspNetCore.Http.HttpResults.Results%606) in the signature and in the body of the handler, as shown in the following example: +* Use [`Results`](xref:Microsoft.AspNetCore.Http.HttpResults.Results%606) in the signature and [`TypedResults`](xref:Microsoft.AspNetCore.Http.TypedResults) in the body of the handler, as shown in the following example: :::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/minimal-apis/samples/MultipleResultTypes/Program.cs" id="snippet_multiple_result_types"::: - The `Results` [union types](https://en.wikipedia.org/wiki/Union_type) declare that a route handler returns multiple `IResult`-implementing concrete types, and any of those types that implement `IEndpointMetadataProvider` will contribute to the endpoint’s metadata. + The `Results` [union types](https://en.wikipedia.org/wiki/Union_type) declare that a route handler returns multiple `IResult`-implementing concrete types, and any of those types that implement [`IEndpointMetadataProvider`](xref:Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider) will contribute to the endpoint’s metadata. The union types implement implicit cast operators. These operators enable the compiler to automatically convert the types specified in the generic arguments to an instance of the union type. This capability has the added benefit of providing compile-time checking that a route handler only returns the results that it declares it does. Attempting to return a type that isn't declared as one of the generic arguments to `Results` results in a compilation error. @@ -376,26 +366,26 @@ If an endpoint can return different response types in different scenarios, you c In controller-based apps, ASP.NET Core can extract the response metadata from the action method signature, attributes, and conventions. -* You can use the or attribute to specify the status code, the type of the response body, and content type(s) of a response from an action method. -* You can use the or attribute to specify the type of the response body. -* You can use the attribute to specify the response body type for the "default" response. -* You can use the attribute to specify the response body type for an error response. However, be aware that this is only complements the status code and content type(s) specified by an attribute with a 4XX status code. +* You can use the [`[ProducesResponseType]`](xref:Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute) or [`ProducesResponseTypeAttribute`](xref:Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute%601) attribute to specify the status code, the type of the response body, and content type(s) of a response from an action method. +* You can use the [`[Produces]`](xref:Microsoft.AspNetCore.Mvc.ProducesAttribute) or [`ProducesAttribute`](xref:Microsoft.AspNetCore.Mvc.ProducesAttribute%601) attribute to specify the type of the response body. +* You can use the [`[ProducesDefaultResponseType]`](xref:Microsoft.AspNetCore.Mvc.ProducesDefaultResponseTypeAttribute) attribute to specify the response body type for the "default" response. +* You can use the [`[ProducesErrorResponseType]`](xref:Microsoft.AspNetCore.Mvc.ProducesErrorResponseTypeAttribute) attribute to specify the response body type for an error response. However, be aware that this is only complements the status code and content type(s) specified by an [`[ProducesResponseType]`](xref:Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute) attribute with a 4XX status code. -Only one or attributes may be applied to an action method, but multiple or attributes with different status codes may be applied to a single action method. +Only one [`[Produces]`](xref:Microsoft.AspNetCore.Mvc.ProducesAttribute) or [`ProducesAttribute`](xref:Microsoft.AspNetCore.Mvc.ProducesAttribute%601) attributes may be applied to an action method, but multiple [`[ProducesResponseType]`](xref:Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute) or [`ProducesResponseTypeAttribute`](xref:Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute%601) attributes with different status codes may be applied to a single action method. All of the above attributes can be applied to individual action methods or to the controller class where it applies to all action methods in the controller. When not specified by an attribute: * the status code for the response defaults to 200, -* the schema for the response body of 2xx responses may be inferred from the return type of the action method, e.g. from `T` in , but otherwise is considered to be not specified, +* the schema for the response body of 2xx responses may be inferred from the return type of the action method, e.g. from `T` in [`ActionResult`](xref:Microsoft.AspNetCore.Mvc.ActionResult%601), but otherwise is considered to be not specified, * the schema for the response body of 4xx responses is inferred to be a problem details object, * the schema for the response body of 3xx and 5xx responses is considered to be not specified, * the content-type for the response body can be inferred from the return type of the action method and the set of output formatters. -Note that there are no compile-time checks to ensure that the response metadata specified with a attribute is consistent with the actual behavior of the action method, +Note that there are no compile-time checks to ensure that the response metadata specified with a [`[ProducesResponseType]`](xref:Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute) attribute is consistent with the actual behavior of the action method, which may return a different status code or response body type than specified by the metadata. -In controller-based apps, ASP.NET responds with a ProblemDetails response type when model validation fails or when the action method returns a result with a 4xx or 5xx HTTP status code. Validation errors typically use the 400 status code, so you can use the attribute to specify the error response for an action, as shown in the following example: +In controller-based apps, ASP.NET responds with a ProblemDetails response type when model validation fails or when the action method returns a result with a 4xx or 5xx HTTP status code. Validation errors typically use the 400 status code, so you can use the [`[ProducesResponseType]`](xref:Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute) attribute to specify the error response for an action, as shown in the following example: ```csharp [HttpPut("/todos/{id}")] @@ -419,8 +409,8 @@ The mechanism for specifying an endpoint that should be excluded depends on the Minimal APIs support two strategies for excluding a given endpoint from the OpenAPI document: -* -* +* [`ExcludeFromDescription`](xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.ExcludeFromDescription%2A) extension method +* [`[ExcludeFromDescription]`](xref:Microsoft.AspNetCore.Routing.ExcludeFromDescriptionAttribute) attribute The following sample demonstrates the different strategies for excluding a given endpoint from the generated OpenAPI document. @@ -435,7 +425,7 @@ app.MapGet("/attributes", ##### [Controllers](#tab/controllers) -In controller-based apps, the attribute can be used to exclude an endpoint or all endpoints in a controller class from the OpenAPI document. +In controller-based apps, the [`[ApiExplorerSettings]`](xref:Microsoft.AspNetCore.Mvc.ApiExplorerSettingsAttribute) attribute can be used to exclude an endpoint or all endpoints in a controller class from the OpenAPI document. The following example demonstrates how to exclude an endpoint from the generated OpenAPI document: @@ -453,12 +443,12 @@ The following example demonstrates how to exclude an endpoint from the generated C# classes or records used in request or response bodies are represented as schemas in the generated OpenAPI document. By default, only public properties are represented in the schema, but there are - to also create schema properties for fields. +[`JsonSerializerOptions`](xref:System.Text.Json.JsonSerializerOptions) to also create schema properties for fields. -When the is set to camel-case (this is the default +When the [`PropertyNamingPolicy`](xref:System.Text.Json.JsonSerializerOptions.PropertyNamingPolicy) is set to camel-case (this is the default in ASP.NET web applications), property names in a schema are the camel-case form of the class or record property name. -The can be used on an individual property to specify the name +The [`[JsonPropertyName]`](xref:System.Text.Json.Serialization.JsonPropertyNameAttribute) can be used on an individual property to specify the name of the property in the schema. #### type and format @@ -498,13 +488,13 @@ The following table summarizes attributes from the `System.ComponentModel` names | Attribute | Description | | ---------------------------- | ----------- | -| | Sets the `description` of a property in the schema. | -| | Marks a property as `required` in the schema. | -| | Sets the `default` value of a property in the schema. | -| | Sets the `minimum` and `maximum` value of an integer or number. | -| | Sets the `minLength` of a string. | -| | Sets the `maxLength` of a string. | -| | Sets the `pattern` of a string. | +| [`[Description]`](xref:System.ComponentModel.DescriptionAttribute) | Sets the `description` of a property in the schema. | +| [`[Required]`](xref:System.ComponentModel.DataAnnotations.RequiredAttribute) | Marks a property as `required` in the schema. | +| [`[DefaultValue]`](xref:System.ComponentModel.DefaultValueAttribute) | Sets the `default` value of a property in the schema. | +| [`[Range]`](xref:System.ComponentModel.DataAnnotations.RangeAttribute) | Sets the `minimum` and `maximum` value of an integer or number. | +| [`[MinLength]`](xref:System.ComponentModel.DataAnnotations.MinLengthAttribute) | Sets the `minLength` of a string. | +| [`[MaxLength]`](xref:System.ComponentModel.DataAnnotations.MaxLengthAttribute) | Sets the `maxLength` of a string. | +| [`[RegularExpression]`](xref:System.ComponentModel.DataAnnotations.RegularExpressionAttribute) | Sets the `pattern` of a string. | Note that in controller-based apps, these attributes add filters to the operation to validate that any incoming data satisfies the constraints. In Minimal APIs, these attributes set the metadata in the generated schema but validation must be performed explicitly via an endpoint filter, in the route handler's logic, or via a third-party package. @@ -516,28 +506,28 @@ Properties can also be marked as `required` with the [required](/dotnet/csharp/l ##### enum -Enum types in C# are integer-based, but can be represented as strings in JSON with a and a . When an enum type is represented as a string in JSON, the generated schema will have an `enum` property with the string values of the enum. -An enum type without a will be defined as `type: integer` in the generated schema. +Enum types in C# are integer-based, but can be represented as strings in JSON with a [`[JsonConverter]`](xref:System.Text.Json.Serialization.JsonConverterAttribute) and a [`JsonStringEnumConverter`](xref:System.Text.Json.Serialization.JsonStringEnumConverter). When an enum type is represented as a string in JSON, the generated schema will have an `enum` property with the string values of the enum. +An enum type without a [`[JsonConverter]`](xref:System.Text.Json.Serialization.JsonConverterAttribute) will be defined as `type: integer` in the generated schema. -**Note:** The does not set the `enum` values of a property. +**Note:** The [`[AllowedValues]`](xref:System.ComponentModel.DataAnnotations.AllowedValuesAttribute) does not set the `enum` values of a property. ##### nullable -Properties defined as a nullable value or reference type have `nullable: true` in the generated schema. This is consistent with the default behavior of the deserializer, which accepts `null` as a valid value for a nullable property. +Properties defined as a nullable value or reference type have `nullable: true` in the generated schema. This is consistent with the default behavior of the [`Json`](xref:System.Text.Json) deserializer, which accepts `null` as a valid value for a nullable property. ##### additionalProperties -Schemas are generated without an `additionalProperties` assertion by default, which implies the default of `true`. This is consistent with the default behavior of the deserializer, which silently ignores additional properties in a JSON object. +Schemas are generated without an `additionalProperties` assertion by default, which implies the default of `true`. This is consistent with the default behavior of the [`Json`](xref:System.Text.Json) deserializer, which silently ignores additional properties in a JSON object. If the additional properties of a schema should only have values of a specific type, define the property or class as a `Dictionary`. The key type for the dictionary must be `string`. This generates a schema with `additionalProperties` specifying the schema for "type" as the required value types. ##### Metadata for polymorphic types -Use the and attributes on a parent class to to specify the discriminator field and subtypes for a polymorphic type. +Use the [`[JsonPolymorphic]`](xref:System.Text.Json.Serialization.JsonPolymorphicAttribute) and [`[JsonDerivedType]`](xref:System.Text.Json.Serialization.JsonDerivedTypeAttribute) attributes on a parent class to to specify the discriminator field and subtypes for a polymorphic type. -The adds the discriminator field to the schema for each subclass, with an enum specifying the specific discriminator value for the subclass. This attribute also modifies the constructor of each derived class to set the discriminator value. +The [`[JsonDerivedType]`](xref:System.Text.Json.Serialization.JsonDerivedTypeAttribute) adds the discriminator field to the schema for each subclass, with an enum specifying the specific discriminator value for the subclass. This attribute also modifies the constructor of each derived class to set the discriminator value. -An abstract class with a attribute has a `discriminator` field in the schema, but a concrete class with a attribute doesn't have a `discriminator` field. OpenAPI requires that the discriminator property be a required property in the schema, but since the discriminator property isn't defined in the concrete base class, the schema cannot include a `discriminator` field. +An abstract class with a [`[JsonPolymorphic]`](xref:System.Text.Json.Serialization.JsonPolymorphicAttribute) attribute has a `discriminator` field in the schema, but a concrete class with a [`[JsonPolymorphic]`](xref:System.Text.Json.Serialization.JsonPolymorphicAttribute) attribute doesn't have a `discriminator` field. OpenAPI requires that the discriminator property be a required property in the schema, but since the discriminator property isn't defined in the concrete base class, the schema cannot include a `discriminator` field. #### Adding metadata with a schema transformer @@ -583,7 +573,7 @@ builder.Services.AddOpenApi(options => ### Customize the OpenAPI endpoint route -By default, the OpenAPI endpoint registered via a call to `MapOpenApi` exposes the document at the `/openapi/{documentName}.json` endpoint. The following code demonstrates how to customize the route at which the OpenAPI document is registered: +By default, the OpenAPI endpoint registered via a call to [`MapOpenApi`](xref:Microsoft.AspNetCore.Builder.OpenApiEndpointRouteBuilderExtensions.MapOpenApi%2A) exposes the document at the `/openapi/{documentName}.json` endpoint. The following code demonstrates how to customize the route at which the OpenAPI document is registered: ```csharp app.MapOpenApi("/openapi/{documentName}/openapi.json"); @@ -627,17 +617,17 @@ Transformers fall into three categories: * Operation transformers apply to each individual operation. Each individual operation is a combination of path and HTTP method. These can be used to modify parameters or responses on endpoints. * Schema transformers apply to each schema in the document. These can be used to modify the schema of request or response bodies, or any nested schemas. -Transformers can be registered onto the document by calling the [`AddDocumentTransformer`](https://source.dot.net/#Microsoft.AspNetCore.OpenApi/Services/OpenApiOptions.cs,90bbc6506b8eff7a) method on the [`OpenApiOptions`](https://source.dot.net/#Microsoft.AspNetCore.OpenApi/Services/OpenApiOptions.cs,c0a8b420f4ce6918) object. The following snippet shows different ways to register transformers onto the document: +Transformers can be registered onto the document by calling the [`AddDocumentTransformer`](xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions.AddDocumentTransformer%2A) method on the [`OpenApiOptions`](xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions) object. The following snippet shows different ways to register transformers onto the document: * Register a document transformer using a delegate. -* Register a document transformer using an instance of `IOpenApiDocumentTransformer`. -* Register a document transformer using a DI-activated `IOpenApiDocumentTransformer`. +* Register a document transformer using an instance of [`IOpenApiDocumentTransformer`](xref:Microsoft.AspNetCore.OpenApi.IOpenApiDocumentTransformer). +* Register a document transformer using a DI-activated [`IOpenApiDocumentTransformer`](xref:Microsoft.AspNetCore.OpenApi.IOpenApiDocumentTransformer). * Register an operation transformer using a delegate. -* Register an operation transformer using an instance of `IOpenApiOperationTransformer`. -* Register an operation transformer using a DI-activated `IOpenApiOperationTransformer`. +* Register an operation transformer using an instance of [`IOpenApiOperationTransformer`](xref:Microsoft.AspNetCore.OpenApi.IOpenApiOperationTransformer). +* Register an operation transformer using a DI-activated [`IOpenApiOperationTransformer`](xref:Microsoft.AspNetCore.OpenApi.IOpenApiOperationTransformer). * Register a schema transformer using a delegate. -* Register a schema transformer using an instance of `IOpenApiSchemaTransformer`. -* Register a schema transformer using a DI-activated `IOpenApiSchemaTransformer`. +* Register a schema transformer using an instance of [`IOpenApiSchemaTransformer`](xref:Microsoft.AspNetCore.OpenApi.IOpenApiSchemaTransformer). +* Register a schema transformer using a DI-activated [`IOpenApiSchemaTransformer`](xref:Microsoft.AspNetCore.OpenApi.IOpenApiSchemaTransformer). [!code-csharp[](~/fundamentals/minimal-apis/9.0-samples/WebMinOpenApi/Program.cs?name=snippet_transUse&highlight=8-19)] @@ -652,14 +642,14 @@ Transformers execute in first-in first-out order based on registration. In the f Document transformers have access to a context object that includes: * The name of the document being modified. -* The list of `ApiDescriptionGroups` associated with that document. -* The `IServiceProvider` used in document generation. +* The [`ApiDescriptionGroups`](xref:Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescriptionGroupCollectionProvider.ApiDescriptionGroups) associated with that document. +* The [`IServiceProvider`](xref:System.IServiceProvider) used in document generation. Document transformers can also mutate the OpenAPI document that is generated. The following example demonstrates a document transformer that adds some information about the API to the OpenAPI document. [!code-csharp[](~/fundamentals/minimal-apis/9.0-samples/WebMinOpenApi/Program.cs?name=snippet_documenttransformer1)] -Service-activated document transformers can utilize instances from DI to modify the app. The following sample demonstrates a document transformer that uses the `IAuthenticationSchemeProvider` service from the authentication layer. It checks if any JWT bearer-related schemes are registered in the app and adds them to the OpenAPI document's top level: +Service-activated document transformers can utilize instances from DI to modify the app. The following sample demonstrates a document transformer that uses the [`IAuthenticationSchemeProvider`](xref:Microsoft.AspNetCore.Authentication.IAuthenticationSchemeProvider) service from the authentication layer. It checks if any JWT bearer-related schemes are registered in the app and adds them to the OpenAPI document's top level: [!code-csharp[](~/fundamentals/minimal-apis/9.0-samples/WebMinOpenApi/Program.cs?name=snippet_documenttransformer2)] @@ -680,8 +670,8 @@ Operations are unique combinations of HTTP paths and methods in an OpenAPI docum Operation transformers have access to a context object which contains: * The name of the document the operation belongs to. -* The `ApiDescription` associated with the operation. -* The `IServiceProvider` used in document generation. +* The [`ApiDescription`](xref:Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescription) associated with the operation. +* The [`IServiceProvider`](xref:System.IServiceProvider) used in document generation. For example, the following operation transformer adds `500` as a response status code supported by all operations in the document. @@ -698,7 +688,7 @@ Schema transformers have access to a context object which contains: * The name of the document the schema belongs to. * The JSON type information associated with the target schema. -* The `IServiceProvider` used in document generation. +* The [`IServiceProvider`](xref:System.IServiceProvider) used in document generation. For example, the following schema transformer sets the `format` of decimal types to `decimal` instead of `double`: @@ -712,3 +702,4 @@ For example, the following schema transformer sets the `format` of decimal types ::: moniker-end [!INCLUDE[](~/fundamentals/openapi/includes/aspnetcore-openapi6-8.md)] +