diff --git a/aspnetcore/blazor/forms/index.md b/aspnetcore/blazor/forms/index.md index 87ebba5cb8ba..a358c602716c 100644 --- a/aspnetcore/blazor/forms/index.md +++ b/aspnetcore/blazor/forms/index.md @@ -243,7 +243,7 @@ The provides the following ## Clear a form or field -Reset a form by clearing its model back its default state, which can be performed inside or outside of an 's markup: +Reset a form by clearing its model back to its default state, which can be performed inside or outside of an 's markup: ```razor @@ -368,7 +368,7 @@ To disable enhanced form handling: * For an , remove the parameter from the form element (or set it to `false`: `Enhance="false"`). * For an HTML `
`, remove the `data-enhance` attribute from form element (or set it to `false`: `data-enhance="false"`). -Blazor's enhanced navigation and form handing may undo dynamic changes to the DOM if the updated content isn't part of the server rendering. To preserve the content of an element, use the `data-permanent` attribute. +Blazor's enhanced navigation and form handling may undo dynamic changes to the DOM if the updated content isn't part of the server rendering. To preserve the content of an element, use the `data-permanent` attribute. In the following example, the content of the `
` element is updated dynamically by a script when the page loads: diff --git a/aspnetcore/fundamentals/openapi/aspnetcore-openapi.md b/aspnetcore/fundamentals/openapi/aspnetcore-openapi.md index e35b77f02f6a..5dca8f8e3f4f 100644 --- a/aspnetcore/fundamentals/openapi/aspnetcore-openapi.md +++ b/aspnetcore/fundamentals/openapi/aspnetcore-openapi.md @@ -5,21 +5,43 @@ description: Learn how to generate and customize OpenAPI documents in an ASP.NET ms.author: safia monikerRange: '>= aspnetcore-6.0' ms.custom: mvc -ms.date: 2/23/2025 +ms.date: 3/18/2025 uid: fundamentals/openapi/aspnetcore-openapi --- # Generate OpenAPI documents -:::moniker range=">= aspnetcore-9.0" +:::moniker range=">= aspnetcore-10.0" The [`Microsoft.AspNetCore.OpenApi`](https://www.nuget.org/packages/Microsoft.AspNetCore.OpenApi) package provides built-in support for OpenAPI document generation in ASP.NET Core. The package provides the following features: +* Support for generating [OpenAPI version 3.1] documents. +* Support for [JSON Schema draft 2020-12]. * Support for generating OpenAPI documents at run time and accessing them via an endpoint on the app. * Support for "transformer" APIs that allow modifying the generated document. * Support for generating multiple OpenAPI documents from a single app. * Takes advantage of JSON schema support provided by [`System.Text.Json`](/dotnet/api/system.text.json). * Is compatible with native AoT. +[OpenAPI version 3.1]: https://spec.openapis.org/oas/v3.1.1.html +[JSON Schema draft 2020-12]: https://json-schema.org/specification-links#2020-12 + +The default OpenAPI version for generated documents is`3.1`. The version can be changed by explicitly setting the [OpenApiVersion](/dotnet/api/microsoft.aspnetcore.openapi.openapioptions.openapiversion) property of the [OpenApiOptions](/dotnet/api/microsoft.aspnetcore.openapi.openapioptions) in the `configureOptions` delegate parameter of [AddOpenApi](/dotnet/api/microsoft.extensions.dependencyinjection.openapiservicecollectionextensions.addopenapi): + +```csharp +builder.Services.AddOpenApi(options => +{ + // Specify the OpenAPI version to use. + options.OpenApiVersion = Microsoft.OpenApi.OpenApiSpecVersion.OpenApi3_0; +}); +``` + +When generating the OpenAPI document at build time, the OpenAPI version can be selected by setting the `--openapi-version` in the `OpenApiGenerateDocumentsOptions` MSBuild item. + +```xml + + --openapi-version OpenApi3_1 +``` + ## Package installation Install the `Microsoft.AspNetCore.OpenApi` package: @@ -56,6 +78,16 @@ Launch the app and navigate to `https://localhost:/openapi/v1.json` to vie The following sections demonstrate how to customize OpenAPI document generation. +### Generate OpenAPI document in YAML format + +The OpenAPI document can be generated in either JSON or YAML format. By default, the OpenAPI document is generated in JSON format. To generate the OpenAPI document in YAML format, specify the endpoint in the MapOpenApi call with a ".yaml" or ".yml" suffix, as shown in the following example: + +```csharp +app.MapOpenApi("/openapi/{documentName}.yaml"); +``` + +Generating penAPI documents in YAML format at build time is currently not supported, but planned in a future preview. + ### Customize the OpenAPI document name Each OpenAPI document in an app has a unique name. The default document name that is registered is `v1`. @@ -81,12 +113,12 @@ GET http://localhost:5000/openapi/internal.json ### Customize the OpenAPI version of a generated document -By default, OpenAPI document generation creates a document that is compliant with [v3.0 of the OpenAPI specification](https://spec.openapis.org/oas/v3.0.0). The following code demonstrates how to modify the default version of the OpenAPI document: +By default, OpenAPI document generation creates a document that is compliant with [OpenAPI version 3.1](https://spec.openapis.org/oas/v3.1.1.html). The following code demonstrates how to modify the default version of the OpenAPI document: ```csharp builder.Services.AddOpenApi(options => { - options.OpenApiVersion = OpenApiSpecVersion.OpenApi2_0; + options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_0; }); ``` @@ -259,32 +291,14 @@ Create a new ASP.NET Core Web API (Native AOT) project. dotnet new webapiaot ``` -:::moniker-end - -:::moniker range="= aspnetcore-9.0" - -Add the Microsoft.AspNetCore.OpenAPI package. - -```console -dotnet add package Microsoft.AspNetCore.OpenApi -``` - -Update `Program.cs` to enable generating OpenAPI documents. - -```diff -+ builder.Services.AddOpenApi(); - -var app = builder.Build(); - -+ app.MapOpenApi(); -``` - -:::moniker-end - Publish the app. ```console dotnet publish ``` +:::moniker-end + [!INCLUDE[](~/fundamentals/openapi/includes/aspnetcore-openapi6-8.md)] + +[!INCLUDE[](~/fundamentals/openapi/includes/aspnetcore-openapi9.md)] diff --git a/aspnetcore/fundamentals/openapi/include-metadata.md b/aspnetcore/fundamentals/openapi/include-metadata.md index fabf214f505f..77d980c0b8bb 100644 --- a/aspnetcore/fundamentals/openapi/include-metadata.md +++ b/aspnetcore/fundamentals/openapi/include-metadata.md @@ -493,6 +493,8 @@ of the property in the schema. ### type and format +:::moniker range="< aspnetcore-10.0" + The JSON Schema library maps standard C# types to OpenAPI `type` and `format` as follows: | C# Type | OpenAPI `type` | OpenAPI `format` | @@ -520,6 +522,79 @@ Note that object and dynamic types have _no_ type defined in the OpenAPI because The `type` and `format` can also be set with a [Schema Transformer](xref:fundamentals/openapi/customize-openapi#use-schema-transformers). For example, you may want the `format` of decimal types to be `decimal` instead of `double`. +:::moniker-end + +:::moniker range=">= aspnetcore-10.0" + +#### Numeric types + +The JSON Schema library maps standard C# numeric types to OpenAPI `type` and `format` based on the + property of the +used in the app. In ASP.NET Core Web API apps, the default value of this property is `JsonNumberHandling.AllowReadingFromString`. + +When the property is set to `JsonNumberHandling.AllowReadingFromString`, the numeric types are mapped as follows: + +| C# Type | OpenAPI `type` | OpenAPI `format` | Other assertions | +| -------------- | ---------------- | ---------------- | ------------------------------ | +| int | [integer,string] | int32 | pattern `` | +| long | [integer,string] | int64 | pattern `` | +| short | [integer,string] | int16 | pattern `` | +| byte | [integer,string] | uint8 | pattern `` | +| float | [number,string] | float | pattern `` | +| double | [number,string] | double | pattern `` | +| decimal | [number,string] | double | pattern `` | + + + +If the app is configured to produce OpenAPI 3.0 or OpenAPI v2 documents, where the `type` field cannot have an array value, the `type` field is dropped. + +When the property is set to `JsonNumberHandling.Strict`, the numeric types are mapped as follows: + +| C# Type | OpenAPI `type` | OpenAPI `format` | +| -------------- | -------------- | ---------------- | +| int | integer | int32 | +| long | integer | int64 | +| short | integer | int16 | +| byte | integer | uint8 | +| float | number | float | +| double | number | double | +| decimal | number | double | + +#### String types + +The following table shows how C# types map to `string` type properties in the generated OpenAPI document: + +| C# Type | OpenAPI `type` | OpenAPI `format` | Other assertions | +| -------------- | -------------- | ---------------- | ------------------------------ | +| string | string | | | +| char | string | char | minLength: 1, maxLength: 1 | +| byte[] | string | byte | | +| DateTimeOffset | string | date-time | | +| DateOnly | string | date | | +| TimeOnly | string | time | | +| Uri | string | uri | | +| Guid | string | uuid | | + +#### Other types + +Other C# types are represented in the generated OpenAPI document as shown in the following table: + +| C# Type | OpenAPI `type` | OpenAPI `format` | +| -------------- | -------------- | ---------------- | +| bool | boolean | | +| object | _omitted_ | | +| dynamic | _omitted_ | | + +:::moniker-end + ### Use attributes to add metadata ASP.NET uses metadata from attributes on class or record properties to set metadata on the corresponding properties of the generated schema. @@ -600,8 +675,31 @@ An enum type without a [`[JsonConverter]`](xref:System.Text.Json.Serialization. #### nullable +:::moniker range="< aspnetcore-10.0" + 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. +:::moniker-end +:::moniker range=">= aspnetcore-10.0" + +Properties defined as a nullable value or reference type appear in the generated schema with a `type` keyword whose value is an array that includes `null` as one of the types. This is consistent with the default behavior of the deserializer, which accepts `null` as a valid value for a nullable property. + +For example, a C# property defined as `string?` is represented in the generated schema as: + +```json + "nullableString": { + "description": "A property defined as string?", + "type": [ + "null", + "string" + ] + }, +``` + +If the app is configured to produce OpenAPI v3.0 or OpenAPI v2 documents, nullable value or reference types have `nullable: true` in the generated schema because these OpenAPI versions do not allow the `type` field to be an array. + +:::moniker-end + #### 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. diff --git a/aspnetcore/fundamentals/openapi/includes/aspnetcore-openapi9.md b/aspnetcore/fundamentals/openapi/includes/aspnetcore-openapi9.md new file mode 100644 index 000000000000..756c29f61ddc --- /dev/null +++ b/aspnetcore/fundamentals/openapi/includes/aspnetcore-openapi9.md @@ -0,0 +1,272 @@ +:::moniker range="= aspnetcore-9.0" + +The [`Microsoft.AspNetCore.OpenApi`](https://www.nuget.org/packages/Microsoft.AspNetCore.OpenApi) package provides built-in support for OpenAPI document generation in ASP.NET Core. The package provides the following features: + +* Support for generating OpenAPI documents at run time and accessing them via an endpoint on the app. +* Support for "transformer" APIs that allow modifying the generated document. +* Support for generating multiple OpenAPI documents from a single app. +* Takes advantage of JSON schema support provided by [`System.Text.Json`](/dotnet/api/system.text.json). +* Is compatible with native AoT. + +## Package installation + +Install the `Microsoft.AspNetCore.OpenApi` package: + +### [Visual Studio](#tab/visual-studio) + +Run the following command from the **Package Manager Console**: + + ```powershell + Install-Package Microsoft.AspNetCore.OpenApi +``` + +### [.NET CLI](#tab/net-cli) + +Run the following command: + +```dotnetcli +dotnet add package Microsoft.AspNetCore.OpenApi +``` +--- + +## Configure OpenAPI document generation + +The following code: + +* Adds OpenAPI services using the extension method on the app builder's service collection. +* Maps an endpoint for viewing the OpenAPI document in JSON format with the extension method on the app. + +[!code-csharp[](~/fundamentals/openapi/samples/9.x/WebMinOpenApi/Program.cs?name=snippet_first&highlight=3,9)] + +Launch the app and navigate to `https://localhost:/openapi/v1.json` to view the generated OpenAPI document. + +## Options to Customize OpenAPI document generation + +The following sections demonstrate how to customize OpenAPI document generation. + +### Customize the OpenAPI document name + +Each OpenAPI document in an app has a unique name. The default document name that is registered is `v1`. + +```csharp +builder.Services.AddOpenApi(); // Document name is v1 +``` + +The document name can be modified by passing the name as a parameter to the call. + +```csharp +builder.Services.AddOpenApi("internal"); // Document name is internal +``` + +The document name surfaces in several places in the OpenAPI implementation. + +When fetching the generated OpenAPI document, the document name is provided as the `documentName` parameter argument in the request. The following requests resolve the `v1` and `internal` documents. + +```bash +GET http://localhost:5000/openapi/v1.json +GET http://localhost:5000/openapi/internal.json +``` + +### Customize the OpenAPI version of a generated document + +By default, OpenAPI document generation creates a document that is compliant with [v3.0 of the OpenAPI specification](https://spec.openapis.org/oas/v3.0.0). The following code demonstrates how to modify the default version of the OpenAPI document: + +```csharp +builder.Services.AddOpenApi(options => +{ + options.OpenApiVersion = OpenApiSpecVersion.OpenApi2_0; +}); +``` + +### Customize the OpenAPI endpoint route + +By default, the OpenAPI endpoint registered via a call to 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"); +``` + +It's possible, but not recommended, to remove the `documentName` route parameter from the endpoint route. When the `documentName` route parameter is removed from the endpoint route, the framework attempts to resolve the document name from the query parameter. Not providing the `documentName` in either the route or query can result in unexpected behavior. + +### Customize the OpenAPI endpoint + +Because the OpenAPI document is served via a route handler endpoint, any customization that is available to standard minimal endpoints is available to the OpenAPI endpoint. + +#### Limit OpenAPI document access to authorized users + +The OpenAPI endpoint doesn't enable any authorization checks by default. However, authorization checks can be applied to the OpenAPI document. In the following code, access to the OpenAPI document is limited to those with the `tester` role: + +[!code-csharp[](~/fundamentals/openapi/samples/9.x/WebMinOpenApi/Program.cs?name=snippet_mapopenapiwithauth)] + +#### Cache generated OpenAPI document + +The OpenAPI document is regenerated every time a request to the OpenAPI endpoint is sent. Regeneration enables transformers to incorporate dynamic app state into their operation. For example, regenerating a request with details of the HTTP context. When applicable, the OpenAPI document can be cached to avoid executing the document generation pipeline on each HTTP request. + +[!code-csharp[](~/fundamentals/openapi/samples/9.x/WebMinOpenApi/Program.cs?name=snippet_mapopenapiwithcaching)] + +## Generate multiple OpenAPI documents + +In some scenarios, it's helpful to generate multiple OpenAPI documents with different content from a single ASP.NET Core API app. These scenarios include: + +* Generating OpenAPI documentation for different audiences, such as public and internal APIs. +* Generating OpenAPI documentation for different versions of an API. +* Generating OpenAPI documentation for different parts of an app, such as a frontend and backend API. + +To generate multiple OpenAPI documents, call the extension method once for each document, specifying a different document name in the first parameter each time. + +```csharp +builder.Services.AddOpenApi("v1"); +builder.Services.AddOpenApi("v2"); +``` + +Each invocation of can specify its own set of options, so that you can choose to use the same or different customizations for each OpenAPI document. + +The framework uses the delegate method of to determine which endpoints to include in each document. + +For each document, the delegate method is called for each endpoint in the app, passing the object for the endpoint. The method returns a boolean value indicating whether the endpoint should be included in the document. The object: + +* contains information about the endpoint, such as the HTTP method, route, and response types +* Metadata attached to the endpoint via attributes or extension methods. + +The default implementation of this delegate uses the field of . The delegate is set on an endpoint using either the extension method or the attribute. `WithGroupName` or the `EndpointGroupName` attribute determines which endpoints to include in the document. Any endpoint that has not been assigned a group name is included all OpenAPI documents. + +```csharp + // Include endpoints without a group name or with a group name that matches the document name + ShouldInclude = (description) => description.GroupName == null || description.GroupName == DocumentName; +``` + +You can customize the delegate method to include or exclude endpoints based on any criteria you choose. + +## Generate OpenAPI documents at build-time + +In typical web apps, OpenAPI documents are generated at run-time and served via an HTTP request to the app server. + +In some scenarios, it's helpful to generate the OpenAPI document during the app's build step. These scenarios include: + +* Generating OpenAPI documentation that is committed into source control. +* Generating OpenAPI documentation that is used for spec-based integration testing. +* Generating OpenAPI documentation that is served statically from the web server. + +To add support for generating OpenAPI documents at build time, install the `Microsoft.Extensions.ApiDescription.Server` package: + +### [Visual Studio](#tab/visual-studio) + +Run the following command from the **Package Manager Console**: + + ```powershell + Install-Package Microsoft.Extensions.ApiDescription.Server +``` + +### [.NET CLI](#tab/net-cli) + +Run the following command in the directory that contains the project file: + +```dotnetcli +dotnet add package Microsoft.Extensions.ApiDescription.Server +``` + +--- + +Upon installation, this package: + +* Automatically generates the Open API document(s) associated with the app during build. +* Populates the Open API documents in the app's output directory. + +If multiple documents are registered, ***and*** document name is ***not*** `v1`, it's post-fixed with the document name. E.g., `{ProjectName}_{DocumentName}.json`. + +# [Visual Studio Code](#tab/visual-studio-code) + +```powershell +dotnet build +type obj\{ProjectName}.json +``` + +# [.NET Core CLI](#tab/netcore-cli) + +```cli +dotnet build +cat obj/{ProjectName}.json +``` + +--- + +### Customizing build-time document generation + +#### Modifying the output directory of the generated Open API file + +By default, the generated OpenAPI document will be emitted to the app's output directory. To modify the location of the emitted file, set the target path in the `OpenApiDocumentsDirectory` property. + +```xml + + . + +``` + +The value of `OpenApiDocumentsDirectory` is resolved relative to the project file. Using the `.` value above will emit the OpenAPI document in the same directory as the project file. + +#### Modifying the output file name + +By default, the generated OpenAPI document will have the same name as the app's project file. To modify the name of the emitted file, set the `--file-name` argument in the `OpenApiGenerateDocumentsOptions` property. + +```xml + + --file-name my-open-api + +``` + +#### Selecting the OpenAPI document to generate + +Some apps may be configured to emit multiple OpenAPI documents. Multiple OpenAPI documents may be generated for different versions of an API or to distinguish between public and internal APIs. By default, the build-time document generator emits files for all documents that are configured in an app. To only emit for a single document name, set the `--document-name` argument in the `OpenApiGenerateDocumentsOptions` property. + +```xml + + --document-name v2 + +``` + +### Customizing run-time behavior during build-time document generation + +Build-time OpenAPI document generation functions by launching the apps entrypoint with a mock server implementation. A mock server is required to produce accurate OpenAPI documents because all information in the OpenAPI document can't be statically analyzed. Because the apps entrypoint is invoked, any logic in the apps startup is invoked. This includes code that injects services into the [DI container](xref:fundamentals/dependency-injection) or reads from configuration. In some scenarios, it's necessary to restrict the code paths that will run when the apps entry point is being invoked from build-time document generation. These scenarios include: + +* Not reading from certain configuration strings. +* Not registering database-related services. + +In order to restrict these code paths from being invoked by the build-time generation pipeline, they can be conditioned behind a check of the entry assembly: + +:::code language="csharp" source="~/fundamentals/openapi/samples/9.x/AspireApp1/AspireApp1.Web/Program.cs" highlight="5-8"::: + +[AddServiceDefaults](https://source.dot.net/#TestingAppHost1.ServiceDefaults/Extensions.cs,0f0d863053754768,references) adds common .NET Aspire services such as service discovery, resilience, health checks, and OpenTelemetry. + +## Trimming and Native AOT + +OpenAPI in ASP.NET Core supports trimming and native AOT. The following steps create and publish an OpenAPI app with trimming and native AOT: + +Create a new ASP.NET Core Web API (Native AOT) project. + +```console +dotnet new webapiaot +``` + +Add the Microsoft.AspNetCore.OpenAPI package. + +```console +dotnet add package Microsoft.AspNetCore.OpenApi +``` + +Update `Program.cs` to enable generating OpenAPI documents. + +```diff ++ builder.Services.AddOpenApi(); + +var app = builder.Build(); + ++ app.MapOpenApi(); +``` + +Publish the app. + +```console +dotnet publish +``` + +:::moniker-end diff --git a/aspnetcore/release-notes/aspnetcore-10.0.md b/aspnetcore/release-notes/aspnetcore-10.0.md index b08561850278..2b821741f388 100644 --- a/aspnetcore/release-notes/aspnetcore-10.0.md +++ b/aspnetcore/release-notes/aspnetcore-10.0.md @@ -4,7 +4,7 @@ author: rick-anderson description: Learn about the new features in ASP.NET Core 10.0. ms.author: riande ms.custom: mvc -ms.date: 04/10/2025 +ms.date: 4/10/2025 uid: aspnetcore-10 --- # What's new in ASP.NET Core 10.0 @@ -51,8 +51,6 @@ This section describes new features for OpenAPI. [!INCLUDE[](~/release-notes/aspnetcore-10/includes/OpenApiPopulateXMLDocComments.md)] -[!INCLUDE[](~/release-notes/aspnetcore-10/includes/OpenApiNetV2Prev7.md)] - [!INCLUDE[](~/release-notes/aspnetcore-10/includes/webapiaotTemplateAddedOpenAPI.md)] ## Authentication and authorization diff --git a/aspnetcore/release-notes/aspnetcore-10/includes/openApi.md b/aspnetcore/release-notes/aspnetcore-10/includes/openApi.md index bae9c2b0957f..867c0e026738 100644 --- a/aspnetcore/release-notes/aspnetcore-10/includes/openApi.md +++ b/aspnetcore/release-notes/aspnetcore-10/includes/openApi.md @@ -11,6 +11,9 @@ Some of the changes you will see in the generated OpenAPI document include: * Nullable types no longer have the `nullable: true` property in the schema. * Instead of a `nullable: true` property, they have a `type` keyword whose value is an array that includes `null` as one of the types. +* Properties or parameters defined as a C# `int` or `long` now appear in the generated OpenAPI document without the `type: integer` field +and have a `pattern` field limiting the value to digits. +This happens when the property in the is set to `AllowReadingFromString`, the default for ASP.NET Core Web apps. To enable C# `int` and `long` to be represented in the OpenAPI document as `type: integer`, set the property to `Strict`. With this feature, the default OpenAPI version for generated documents is`3.1`. The version can be changed by explicitly setting the [OpenApiVersion](/dotnet/api/microsoft.aspnetcore.openapi.openapioptions.openapiversion) property of the [OpenApiOptions](/dotnet/api/microsoft.aspnetcore.openapi.openapioptions) in the `configureOptions` delegate parameter of [AddOpenApi](/dotnet/api/microsoft.extensions.dependencyinjection.openapiservicecollectionextensions.addopenapi). @@ -34,6 +37,10 @@ OpenAPI 3.1 support was primarily added in the following [PR](https://github.com ### OpenAPI 3.1 breaking changes Support for OpenAPI 3.1 requires an update to the underlying OpenAPI.NET library to a new major version, 2.0. This new version has some breaking changes from the previous version. The breaking changes may impact apps if they have any document, operation, or schema transformers. +Breaking changes in this iteration include the following: + +* Entities within the OpenAPI document, like operations and parameters, are typed as interfaces. Concrete implementations exist for the inlined and referenced variants of an entity. For example, an `IOpenApiSchema` can either be an inlined `OpenApiSchema` or an `OpenApiSchemaReference` that points to a schema defined elsewhere in the document. +* The `Nullable` property has been removed from the `OpenApiSchema` type. To determine if a type is nullable, evaluate if the `OpenApiSchema.Type` property sets `JsonSchemaType.Null`. One of the most significant changes is that the `OpenApiAny` class has been dropped in favor of using `JsonNode` directly. Transformers that use `OpenApiAny` need to be updated to use `JsonNode`. The following diff shows the changes in schema transformer from .NET 9 to .NET 10: @@ -61,7 +68,7 @@ options.AddSchemaTransformer((schema, context, cancellationToken) => Note that these changes are necessary even when only configuring the OpenAPI version to 3.0. -### OpenAPI in Yaml +### OpenAPI in YAML ASP.NET now supports serving the generated OpenAPI document in YAML format. YAML can be more concise than JSON, eliminating curly braces and quotation marks when these can be inferred. YAML also supports multi-line strings, which can be useful for long descriptions. diff --git a/aspnetcore/release-notes/aspnetcore-10/includes/responseDescProducesResponseType.md b/aspnetcore/release-notes/aspnetcore-10/includes/responseDescProducesResponseType.md index c9602f685f2d..25ecbbb9e46f 100644 --- a/aspnetcore/release-notes/aspnetcore-10/includes/responseDescProducesResponseType.md +++ b/aspnetcore/release-notes/aspnetcore-10/includes/responseDescProducesResponseType.md @@ -4,7 +4,8 @@ The [ProducesAttribute](/dotnet/api/microsoft.aspnetcore.mvc.producesattribute-1 ```csharp [HttpGet(Name = "GetWeatherForecast")] -[ProducesResponseType>(StatusCodes.Status200OK, Description = "The weather forecast for the next 5 days.")] +[ProducesResponseType>(StatusCodes.Status200OK, + Description = "The weather forecast for the next 5 days.")] public IEnumerable Get() { ``` diff --git a/aspnetcore/security/authentication/configure-jwt-bearer-authentication.md b/aspnetcore/security/authentication/configure-jwt-bearer-authentication.md index 14448dc57ef7..447590646b73 100644 --- a/aspnetcore/security/authentication/configure-jwt-bearer-authentication.md +++ b/aspnetcore/security/authentication/configure-jwt-bearer-authentication.md @@ -248,7 +248,7 @@ See [OAuth 2.0 Token Exchange](https://datatracker.ietf.org/doc/html/rfc8693) Using the [Microsoft Identity Web authentication library](/entra/msal/dotnet/microsoft-identity-web/) is the easiest and a secure approach. It only works with Microsoft Entra ID, Microsoft Entra External ID. -For more information, see [[Microsoft identity platform and OAuth 2.0 On-Behalf-Of flow](/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow) +For more information, see [Microsoft identity platform and OAuth 2.0 On-Behalf-Of flow](/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow). ### Use the same delegated access token sent to the API diff --git a/aspnetcore/security/preventing-open-redirects.md b/aspnetcore/security/preventing-open-redirects.md index acd0804ec3e5..0cd967b36fb1 100644 --- a/aspnetcore/security/preventing-open-redirects.md +++ b/aspnetcore/security/preventing-open-redirects.md @@ -50,7 +50,7 @@ public IActionResult SomeAction(string redirectUrl) `LocalRedirect` will throw an exception if a non-local URL is specified. Otherwise, it behaves just like the `Redirect` method. -### IsLocalUrl +### IUrlHelper.IsLocalUrl Use the method to test URLs before redirecting: @@ -70,4 +70,25 @@ private IActionResult RedirectToLocal(string returnUrl) } ``` -The `IsLocalUrl` method protects users from being inadvertently redirected to a malicious site. You can log the details of the URL that was provided when a non-local URL is supplied in a situation where you expected a local URL. Logging redirect URLs may help in diagnosing redirection attacks. +The `IUrlHelper.IsLocalUrl` method protects users from being inadvertently redirected to a malicious site. You can log the details of the URL that was provided when a non-local URL is supplied in a situation where you expected a local URL. Logging redirect URLs may help in diagnosing redirection attacks. + +:::moniker range=">= aspnetcore-10.0" + +### Detect if URL is local using `RedirectHttpResult.IsLocalUrl` + +The [`RedirectHttpResult.IsLocalUrl(url)`](https://source.dot.net/#Microsoft.AspNetCore.Http.Results/RedirectHttpResult.cs,c0ece2e6266cb369) helper method detects if a URL is local. A URL is considered local if the following are true: + +* It doesn't have the [host](https://developer.mozilla.org/docs/Web/API/URL/host) or [authority](https://developer.mozilla.org/docs/Web/URI/Authority) section. +* It has an [absolute path](https://developer.mozilla.org/docs/Learn_web_development/Howto/Web_mechanics/What_is_a_URL#absolute_urls_vs._relative_urls). + +URLs using [virtual paths](/previous-versions/aspnet/ms178116(v=vs.100)) `"~/"` are also local. + +`IsLocalUrl` is useful for validating URLs before redirecting to them to prevent [open redirection attacks](https://brightsec.com/blog/open-redirect-vulnerabilities/). + +```csharp +if (RedirectHttpResult.IsLocalUrl(url)) +{ + return Results.LocalRedirect(url); +} + +:::moniker-end