Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Inline JavaScript isn't recommended for Blazor apps. We recommend using [JS coll

:::moniker range=">= aspnetcore-8.0"

Only place a `<script>` tag in a component file (`.razor`) if the component is guaranteed to adopt [static server-side rendering (static SSR)](xref:blazor/fundamentals/index#client-and-server-rendering-concepts) because the `<script>` tag can't be updated dynamically. Placing a `<script>` tag in a component file doesn't produce a compile-time warning or error, but script loading behavior might not match your expectations in components that don't adopt static SSR when the component is rendered.
Only place a `<script>` tag in a component file (`.razor`) if the component is guaranteed to adopt [static server-side rendering (static SSR)](xref:blazor/fundamentals/index#client-and-server-rendering-concepts) because the `<script>` tag can't be updated dynamically. Placing a `<script>` tag in a component file doesn't produce a compile-time warning or error, but script loading behavior might not match your expectations in components that adopt an interactive render mode.

:::moniker-end

Expand Down
2 changes: 1 addition & 1 deletion aspnetcore/fundamentals/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ The request handling pipeline is composed as a series of middleware components.

By convention, a middleware component is added to the pipeline by invoking a `Use{Feature}` extension method. The use of methods named `Use{Feature}` to add middleware to an app is illustrated in the following code:

:::code language="csharp" source="~/fundamentals/index/samples/9.0/BlazorWebAppMovies/Program.cs" id="snippet_middleware" highlight="24-26,29,32":::
:::code language="csharp" source="~/fundamentals/index/samples/9.0/BlazorWebAppMovies/Program.cs" id="snippet_middleware" highlight="26-28,30,32":::

For more information, see <xref:fundamentals/middleware/index>.

Expand Down
36 changes: 33 additions & 3 deletions aspnetcore/fundamentals/openapi/aspnetcore-openapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ dotnet add package Microsoft.AspNetCore.OpenApi

The following code:

* Adds OpenAPI services.
* Enables the endpoint for viewing the OpenAPI document in JSON format.
* Adds OpenAPI services using the <xref:Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi%2A> extension method on the app builder's service collection.
* Maps an endpoint for viewing the OpenAPI document in JSON format with the <xref:Microsoft.AspNetCore.Builder.OpenApiEndpointRouteBuilderExtensions.MapOpenApi%2A> extension method on the app.

[!code-csharp[](~/fundamentals/openapi/samples/9.x/WebMinOpenApi/Program.cs?name=snippet_first&highlight=3,7)]

Expand All @@ -64,7 +64,7 @@ Each OpenAPI document in an app has a unique name. The default document name tha
builder.Services.AddOpenApi(); // Document name is v1
```

The document name can be modified by passing the name as a parameter to the `AddOpenApi` call.
The document name can be modified by passing the name as a parameter to the <xref:Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi%2A> call.

```csharp
builder.Services.AddOpenApi("internal"); // Document name is internal
Expand Down Expand Up @@ -116,6 +116,36 @@ The OpenAPI document is regenerated every time a request to the OpenAPI endpoint

[!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 application, such as a frontend and backend API.

To generate multiple OpenAPI documents, call the <xref:Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi%2A> 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 <xref:Microsoft.Extensions.DependencyInjection.OpenApiServiceCollectionExtensions.AddOpenApi%2A> 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 <xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions.ShouldInclude> delegate method of <xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions> to determine which endpoints to include in each document.

For each document, the <xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions.ShouldInclude> delegate method is called for each endpoint in the application, passing the <xref:Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescription> object for the endpoint. The method returns a boolean value indicating whether the endpoint should be included in the document. The <xref:Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescription> object contains information about the endpoint, such as the HTTP method, route, and response types, as well as metadata attached to the endpoint via attributes or extension methods.

The default implementation of this delegate uses the <xref:Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescription.GroupName> field of <xref:Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescription>, which is set on an endpoint using either the <xref:Microsoft.AspNetCore.Builder.RoutingEndpointConventionBuilderExtensions.WithGroupName%2A> extension method or the <xref:Microsoft.AspNetCore.Routing.EndpointGroupNameAttribute> attribute, to determine 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 <xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions.ShouldInclude> delegate method to include or exclude endpoints based on any criteria you choose.

## Generate OpenAPI documents at build-time

In typical web applications, OpenAPI documents are generated at run-time and served via an HTTP request to the application server.
Expand Down
47 changes: 40 additions & 7 deletions aspnetcore/fundamentals/openapi/customize-openapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ uid: fundamentals/openapi/customize-openapi

## OpenAPI document transformers

This section demonstrates how to customize OpenAPI documents with transformers.

### Customize OpenAPI documents with transformers

Transformers provide an API for modifying the OpenAPI document with user-defined customizations. Transformers are useful for scenarios like:

* Adding parameters to all operations in a document.
Expand Down Expand Up @@ -50,7 +46,7 @@ Transformers execute in first-in first-out order based on registration. In the f

[!code-csharp[](~/fundamentals/openapi/samples/9.x/WebMinOpenApi/Program.cs?name=snippet_transInOut&highlight=3-9)]

### Use document transformers
## Use document transformers

Document transformers have access to a context object that includes:

Expand All @@ -73,7 +69,7 @@ Document transformers are unique to the document instance they're associated wit

[!code-csharp[](~/fundamentals/openapi/samples/9.x/WebMinOpenApi/Program.cs?name=snippet_multidoc_operationtransformer1)]

### Use operation transformers
## Use operation transformers

Operations are unique combinations of HTTP paths and methods in an OpenAPI document. Operation transformers are helpful when a modification:

Expand All @@ -90,7 +86,7 @@ For example, the following operation transformer adds `500` as a response status

[!code-csharp[](~/fundamentals/openapi/samples/9.x/WebMinOpenApi/Program.cs?name=snippet_operationtransformer1)]

### Use schema transformers
## Use schema transformers

Schemas are the data models that are used in request and response bodies in an OpenAPI document. Schema transformers are useful when a modification:

Expand All @@ -107,6 +103,43 @@ For example, the following schema transformer sets the `format` of decimal types

[!code-csharp[](~/fundamentals/openapi/samples/9.x/WebMinOpenApi/Program.cs?name=snippet_schematransformer1)]

## Customize schema reuse

After all transformers have been applied, the framework makes a pass over the document to transfer certain schemas
to the `components.schemas` section, replacing them with `$ref` references to the transferred schema.
This reduces the size of the document and makes it easier to read.

The details of this processing are complicated and might change in future versions of .NET, but in general:

* Schemas for class/record/struct types are replaced with a `$ref` to a schema in `components.schemas`
if they appear more than once in the document.
* Schemas for primitive types and standard collections are left inline.
* Schemas for enum types are always replaced with a `$ref` to a schema in components.schemas.

Typically the name of the schema in `components.schemas` is the name of the class/record/struct type,
but in some circumstances a different name must be used.

ASP.NET Core lets you customize which schemas are replaced with a `$ref` to a schema in `components.schemas`
using the <xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions.CreateSchemaReferenceId> property of <xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions>.
This property is a delegate that takes a <xref:System.Text.Json.Serialization.Metadata.JsonTypeInfo> object and returns the name of the schema
in `components.schemas` that should be used for that type.
The framework provides a default implementation of this delegate, <xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions.CreateDefaultSchemaReferenceId%2A>
that uses the name of the type, but you can replace it with your own implementation.

As a simple example of this customization, you might choose to always inline enum schemas.
This is done by setting <xref:Microsoft.AspNetCore.OpenApi.OpenApiOptions.CreateSchemaReferenceId> to a delegate
that returns null for enum types, and otherwise returns the value from the default implementation.
The following code shows how to do this:

```csharp
builder.Services.AddOpenApi(options =>
{
// Always inline enum schemas
options.CreateSchemaReferenceId = (type) =>
type.Type.IsEnum ? null : OpenApiOptions.CreateDefaultSchemaReferenceId(type);
});
```

## Additional resources

* <xref:fundamentals/openapi/using-openapi-documents>
Expand Down
4 changes: 2 additions & 2 deletions aspnetcore/fundamentals/openapi/include-metadata.md
Original file line number Diff line number Diff line change
Expand Up @@ -489,8 +489,8 @@ The following table summarizes attributes from the `System.ComponentModel` names
| [`[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. |
| [`[MinLength]`](xref:System.ComponentModel.DataAnnotations.MinLengthAttribute) | Sets the `minLength` of a string or `minItems` of an array. |
| [`[MaxLength]`](xref:System.ComponentModel.DataAnnotations.MaxLengthAttribute) | Sets the `maxLength` of a string or `maxItems` of an array. |
| [`[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.
Expand Down
Loading