Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge to Live #33667

Merged
merged 8 commits into from
Sep 21, 2024
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
2 changes: 1 addition & 1 deletion aspnetcore/fundamentals/error-handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ An alternative approach to using <xref:Microsoft.AspNetCore.Http.ProblemDetailsO

In the preceding code, the minimal API endpoints `/divide` and `/squareroot` return the expected custom problem response on error input.

The API controller endpoints return the default problem response on error input, not the custom problem response. The default problem response is returned because the API controller has written to the response stream, [Problem details for error status codes](/aspnet/core/web-api/#problem-details-for-error-status-codes-1), before [`IProblemDetailsService.WriteAsync`](https://github.com/dotnet/aspnetcore/blob/ce2db7ea0b161fc5eb35710fca6feeafeeac37bc/src/Http/Http.Extensions/src/ProblemDetailsService.cs#L24) is called and the response is **not** written again.
The API controller endpoints return the default problem response on error input, not the custom problem response. The default problem response is returned because the API controller has written to the response stream, [Problem details for error status codes](/aspnet/core/web-api/#problem-details-for-error-status-codes), before [`IProblemDetailsService.WriteAsync`](https://github.com/dotnet/aspnetcore/blob/ce2db7ea0b161fc5eb35710fca6feeafeeac37bc/src/Http/Http.Extensions/src/ProblemDetailsService.cs#L24) is called and the response is **not** written again.

The following `ValuesController` returns <xref:Microsoft.AspNetCore.Mvc.BadRequestResult>, which writes to the response stream and therefore prevents the custom problem response from being returned.

Expand Down
56 changes: 29 additions & 27 deletions aspnetcore/fundamentals/openapi/aspnetcore-openapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ Launch the app and navigate to `https://localhost:<port>/openapi/v1.json` to vie

## Including OpenAPI metadata in an ASP.NET web app

### 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]`.
Expand All @@ -96,7 +98,7 @@ ASP.NET Core does not collect metadata from XML doc comments.

The following sections demonstrate how to include metadata in an app to customize the generated OpenAPI document.

### Summary and description
#### 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.
Expand All @@ -106,7 +108,7 @@ or in minimal APIs, using the `WithSummary` and `WithDescription` extension meth
* `WithSummary`: <xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.WithSummary%2A>
* `WithDescription`: <xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.WithDescription%2A>

#### [Minimal APIs](#tab/minimal-apis)
##### [Minimal APIs](#tab/minimal-apis)

The following sample demonstrates the different strategies for setting summaries and descriptions.

Expand All @@ -123,7 +125,7 @@ app.MapGet("/attributes",
() => "Hello world!");
```

#### [Controllers](#tab/controllers)
##### [Controllers](#tab/controllers)

The following sample demonstrates how to set summaries and descriptions.

Expand All @@ -138,7 +140,7 @@ The following sample demonstrates how to set summaries and descriptions.
```
---

### tags
#### 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,
Expand All @@ -148,7 +150,7 @@ In minimal APIs, tags can be set using either the `[Tags]` attribute or the `Wit
* `[Tags]`: <xref:Microsoft.AspNetCore.Http.TagsAttribute>
* `WithTags`: <xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.WithTags%2A>

#### [Minimal APIs](#tab/minimal-apis)
##### [Minimal APIs](#tab/minimal-apis)

The following sample demonstrates the different strategies for setting tags.

Expand All @@ -161,7 +163,7 @@ app.MapGet("/attributes",
() => "Hello world!");
```

#### [Controllers](#tab/controllers)
##### [Controllers](#tab/controllers)

The following sample demonstrates how to set tags.

Expand All @@ -175,7 +177,7 @@ The following sample demonstrates how to set tags.
```
---

### operationId
#### 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.
Expand All @@ -184,7 +186,7 @@ In minimal APIs, the operationId can be set using either the `[EndpointName]` at
* `[EndpointName]`: <xref:Microsoft.AspNetCore.Routing.EndpointNameAttribute>
* `WithName`: <xref:Microsoft.AspNetCore.Builder.RoutingEndpointConventionBuilderExtensions.WithName%2A>

#### [Minimal APIs](#tab/minimal-apis)
##### [Minimal APIs](#tab/minimal-apis)

The following sample demonstrates the different strategies for setting the operationId.

Expand All @@ -197,7 +199,7 @@ app.MapGet("/attributes",
() => "Hello world!");
```

#### [Controllers](#tab/controllers)
##### [Controllers](#tab/controllers)

The following sample demonstrates how to set the operationId.

Expand All @@ -211,7 +213,7 @@ The following sample demonstrates how to set the operationId.
```
---

### parameters
#### parameters

OpenAPI supports annotating path, query string, header, and cookie parameters that are consumed by an API.

Expand All @@ -221,7 +223,7 @@ The `[Description]` attribute can be used to provide a description for a paramet

* [`Description`](/dotnet/api/system.componentmodel.descriptionattribute)

#### [Minimal APIs](#tab/minimal-apis)
##### [Minimal APIs](#tab/minimal-apis)

The follow sample demonstrates how to set a description for a parameter.

Expand All @@ -230,7 +232,7 @@ app.MapGet("/attributes",
([Description("This is a description.")] string name) => "Hello world!");
```

#### [Controllers](#tab/controllers)
##### [Controllers](#tab/controllers)

The following sample demonstrates how to set a description for a parameter.

Expand All @@ -243,7 +245,7 @@ The following sample demonstrates how to set a description for a parameter.
```
---

### requestBody
#### requestBody

<!-- TODO: Restructure this section to cover both controller-based and minimal API apps -->

Expand Down Expand Up @@ -275,7 +277,7 @@ When no explicit annotation is provided, the framework attempts to determine the
* 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 <xref:Microsoft.AspNetCore.Http.Metadata.IFromBodyMetadata.AllowEmpty> property is set on the [`FromBody`](xref:Microsoft.AspNetCore.Mvc.FromBodyAttribute) attribute.

### Describe response types
#### Describe response types

<!-- TODO: Restructure this section to cover both controller-based and minimal API apps -->

Expand All @@ -302,13 +304,13 @@ app.MapGet("/todos", async (TodoDb db) =>
});
```

#### Set responses for `ProblemDetails`
##### Set responses for `ProblemDetails`

When setting the response type for endpoints that may return a ProblemDetails response, the <xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.ProducesProblem%2A> or <xref:Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.ProducesValidationProblem%2A> extension method or <xref:Microsoft.AspNetCore.Http.TypedResults.Problem%2A?displayProperty=nameWithType> can be used to add the appropriate annotation to the endpoint's metadata.

When there are no explicit annotations provided by one of these strategies, the framework attempts to determine a default response type by examining the signature of the response. This default response is populated under the `200` status code in the OpenAPI definition.

#### Multiple response types
##### Multiple response types

If an endpoint can return different response types in different scenarios, you can provide metadata in the following ways:

Expand All @@ -324,7 +326,7 @@ If an endpoint can return different response types in different scenarios, you c

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<TResult1,TResult2,TResultN>` results in a compilation error.

### Excluding endpoints from the generated document
#### Excluding endpoints from the generated document

<!-- TODO: Add information for controller-based apps in this section -->

Expand All @@ -344,7 +346,7 @@ app.MapGet("/attributes",
() => "Hello world!");
```

## Including OpenAPI metadata for data types
### Including OpenAPI metadata for data types

C# classes or records used in request or response bodies are represented as schemas
in the generated OpenAPI document.
Expand All @@ -357,7 +359,7 @@ of the class or record property name.
The <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
#### type and format

The JSON Schema library maps standard C# types to OpenAPI `type` and `format` as follows:

Expand Down Expand Up @@ -386,7 +388,7 @@ 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](#use-schema-transformers). For example, you may want the `format` of decimal types to be `decimal` instead of `double`.

## Using attributes to add metadata
#### Using 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.

Expand All @@ -404,38 +406,38 @@ The following table summarizes attributes from the `System.ComponentModel` names

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.

## Other sources of metadata for generated schemas
#### Other sources of metadata for generated schemas

### required
##### required

Properties can also be marked as `required` with the [required](/dotnet/csharp/language-reference/proposals/csharp-11.0/required-members#required-modifier) modifier.

### enum
##### enum

Enum types in C# are integer-based, but can be represented as strings in JSON with a <xref:System.Text.Json.Serialization.JsonConverterAttribute> and a <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 <xref:System.Text.Json.Serialization.JsonConverterAttribute> will be defined as `type: integer` in the generated schema.

**Note:** The <xref:System.ComponentModel.DataAnnotations.AllowedValuesAttribute> does not set the `enum` values of a property.

### nullable
##### 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 <xref:System.Text.Json> deserializer, which accepts `null` as a valid value for a nullable property.

### additionalProperties
##### 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 <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<string, type>`. 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
##### Metadata for polymorphic types

Use the <xref:System.Text.Json.Serialization.JsonPolymorphicAttribute> and <xref:System.Text.Json.Serialization.JsonDerivedTypeAttribute> attributes on a parent class to to specify the discriminator field and subtypes for a polymorphic type.

The <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 <xref:System.Text.Json.Serialization.JsonPolymorphicAttribute> attribute has a `discriminator` field in the schema, but a concrete class with a <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
#### Adding metadata with a schema transformer

A schema transformer can be used to override any default metadata or add additional metadata, such as `example` values, to the generated schema. See [Use schema transformers](#use-schema-transformers) for more information.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ ms.author: wpickett
ms.date: 08/22/2024
ms.topic: include
---
> [!NOTE]
> [!WARNING]
> This article uses a local database that doesn't require the user to be authenticated. Production apps should use the most secure authentication flow available. For more information on authentication for deployed test and production apps, see [Secure authentication flows](xref:security/index#secure-authentication-flows).
2 changes: 1 addition & 1 deletion aspnetcore/security/app-secrets.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ File system path:

In the preceding file paths, replace `<user_secrets_id>` with the `UserSecretsId` value specified in the project file.

Don't write code that depends on the location or format of data saved with the Secret Manager tool. These implementation details may change. For example, the secret values aren't encrypted, but could be in the future.
Don't write code that depends on the location or format of data saved with the Secret Manager tool. These implementation details may change. For example, the secret values aren't encrypted.

## Enable secret storage

Expand Down
7 changes: 5 additions & 2 deletions aspnetcore/security/authorization/secure-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ The `SeedData` class creates two accounts: administrator and manager. Use the [S
dotnet user-secrets set SeedUserPW <PW>
```

If a strong password is not specified, an exception is thrown when `SeedData.Initialize` is called.
If a weak password is specified, an exception is thrown when `SeedData.Initialize` is called.

Update the app to use the test password:

Expand Down Expand Up @@ -288,9 +288,12 @@ In the preceding code:

## Test the completed app

> [!WARNING]
> This article uses the [Secret Manager tool](xref:security/app-secrets) to store the password for the seeded user accounts. The Secret Manager tool is used to store sensitive data during local development. For more information on authentication for deployed test and production apps, see [Secure authentication flows](xref:security/index#secure-authentication-flows).

If you haven't already set a password for seeded user accounts, use the [Secret Manager tool](xref:security/app-secrets#secret-manager) to set a password:

* Choose a strong password: Use eight or more characters and at least one upper-case character, number, and symbol. For example, `Passw0rd!` meets the strong password requirements.
* Choose a strong password: Use eight or more characters and at least one upper-case character, number, and symbol.
* Execute the following command from the project's folder, where `<PW>` is the password:

```dotnetcli
Expand Down
9 changes: 4 additions & 5 deletions aspnetcore/security/cors.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,11 +220,11 @@ This section describes the various options that can be set in a CORS policy:

### Set the allowed request headers

To allow specific headers to be sent in a CORS request, called [author request headers](https://xhr.spec.whatwg.org/#request), call <xref:Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicyBuilder.WithHeaders%2A> and specify the allowed headers:
To allow specific headers to be sent in a CORS request, called *author request headers*, call <xref:Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicyBuilder.WithHeaders%2A> and specify the allowed headers:

[!code-csharp[](~/security/cors/8.0sample/Cors/Web2API/Program.cs?name=snippet_sa)]

To allow all [author request headers](https://www.w3.org/TR/cors/#author-request-headers), call <xref:Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicyBuilder.AllowAnyHeader%2A>:
To allow all author request headers, call <xref:Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicyBuilder.AllowAnyHeader%2A>:

[!code-csharp[](~/security/cors/8.0sample/Cors/Web2API/Program.cs?name=snippet_aah)]

Expand Down Expand Up @@ -321,7 +321,7 @@ For some CORS requests, the browser sends an additional [OPTIONS](https://develo
* `multipart/form-data`
* `text/plain`

The rule on request headers set for the client request applies to headers that the app sets by calling `setRequestHeader` on the `XMLHttpRequest` object. The CORS specification calls these headers [author request headers](https://www.w3.org/TR/cors/#author-request-headers). The rule doesn't apply to headers the browser can set, such as `User-Agent`, `Host`, or `Content-Length`.
The rule on request headers set for the client request applies to headers that the app sets by calling `setRequestHeader` on the `XMLHttpRequest` object. The CORS specification calls these headers *author request headers*. The rule doesn't apply to headers the browser can set, such as `User-Agent`, `Host`, or `Content-Length`.

> [!NOTE]
> This article contains URLs created by deploying the [sample code](https://github.com/dotnet/AspNetCore.Docs/tree/live/aspnetcore/security/cors/8.0sample/Cors) to two Azure web sites, `https://cors3.azurewebsites.net` and `https://cors.azurewebsites.net`.
Expand Down Expand Up @@ -360,7 +360,6 @@ The preflight request uses the [HTTP OPTIONS](https://developer.mozilla.org/docs

* [Access-Control-Request-Method](https://developer.mozilla.org/docs/Web/HTTP/Headers/Access-Control-Request-Method): The HTTP method that will be used for the actual request.
* [Access-Control-Request-Headers](https://developer.mozilla.org/docs/Web/HTTP/Headers/Access-Control-Allow-Headers): A list of request headers that the app sets on the actual request. As stated earlier, this doesn't include headers that the browser sets, such as `User-Agent`.
* [Access-Control-Allow-Methods](https://developer.mozilla.org/docs/Web/HTTP/Headers/Access-Control-Allow-Methods)

If the preflight request is denied, the app returns a `200 OK` response but doesn't set the CORS headers. Therefore, the browser doesn't attempt the cross-origin request. For an example of a denied preflight request, see the [Test CORS](#testc6) section of this document.

Expand All @@ -373,7 +372,7 @@ To allow specific headers, call <xref:Microsoft.AspNetCore.Cors.Infrastructure.C

[!code-csharp[](~/security/cors/8.0sample/Cors/Web2API/Program.cs?name=snippet_whx)]

To allow all [author request headers](https://www.w3.org/TR/cors/#author-request-headers), call <xref:Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicyBuilder.AllowAnyHeader%2A>:
To allow all author request headers, call <xref:Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicyBuilder.AllowAnyHeader%2A>:

[!code-csharp[](~/security/cors/8.0sample/Cors/Web2API/Program.cs?name=snippet_aah2)]

Expand Down
Loading