diff --git a/aspnetcore/release-notes/aspnetcore-10/includes/openApi.md b/aspnetcore/release-notes/aspnetcore-10/includes/openApi.md index 867c0e026738..7ad3cfe81732 100644 --- a/aspnetcore/release-notes/aspnetcore-10/includes/openApi.md +++ b/aspnetcore/release-notes/aspnetcore-10/includes/openApi.md @@ -15,22 +15,13 @@ Some of the changes you will see in the generated OpenAPI document include: 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). +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): -```csharp -builder.Services.AddOpenApi(options => -{ - // Specify the OpenAPI version to use. - options.OpenApiVersion = Microsoft.OpenApi.OpenApiSpecVersion.OpenApi3_0; -}); -``` +:::code language="csharp" source="~/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/Program.cs" id="snippet_DefaultOpenApiVersion" highlight="3"::: -When generating the OpenAPI document at build time, the OpenAPI version can be selected by setting the `--openapi-version` in the `OpenApiGenerateDocumentsOptions` MSBuild item. +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_0 -``` +:::code language="xml" source="~/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/WebAppOpenAPI10.csproj" id="snippet_ConfigBuildTimeOpenApiDocVersion" highlight="7"::: OpenAPI 3.1 support was primarily added in the following [PR](https://github.com/dotnet/aspnetcore/pull/59480). @@ -42,29 +33,9 @@ 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: - -```diff -options.AddSchemaTransformer((schema, context, cancellationToken) => -{ - if (context.JsonTypeInfo.Type == typeof(WeatherForecast)) - { -- schema.Example = new OpenApiObject -+ schema.Example = new JsonObject - { -- ["date"] = new OpenApiString(DateTime.Now.AddDays(1).ToString("yyyy-MM-dd")), -+ ["date"] = DateTime.Now.AddDays(1).ToString("yyyy-MM-dd"), -- ["temperatureC"] = new OpenApiInteger(0), -+ ["temperatureC"] = 0, -- ["temperatureF"] = new OpenApiInteger(32), -+ ["temperatureF"] = 32, -- ["summary"] = new OpenApiString("Bracing"), -+ ["summary"] = "Bracing", - }; - } - return Task.CompletedTask; -}); -``` +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: + +:::code language="diff" source="~/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/TransformerJsonNode.cs"::: Note that these changes are necessary even when only configuring the OpenAPI version to 3.0. @@ -74,9 +45,7 @@ ASP.NET now supports serving the generated OpenAPI document in YAML format. YAML To configure an app to serve the generated 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"); -``` +:::code language="csharp" source="~/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/Program.cs" id="snippet_ConfigOpenApiYAML" highlight="3"::: Support for: diff --git a/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/Controllers/WeatherForecastController.cs b/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/Controllers/WeatherForecastController.cs new file mode 100644 index 000000000000..bd33858d25a0 --- /dev/null +++ b/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/Controllers/WeatherForecastController.cs @@ -0,0 +1,26 @@ +using Microsoft.AspNetCore.Mvc; + +namespace WebAppOpenAPI10.Controllers +{ + [ApiController] + [Route("[controller]")] + public class WeatherForecastController : ControllerBase + { + private static readonly string[] Summaries = + [ + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + ]; + + [HttpGet(Name = "GetWeatherForecast")] + public IEnumerable Get() + { + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = Summaries[Random.Shared.Next(Summaries.Length)] + }) + .ToArray(); + } + } +} diff --git a/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/Program.cs b/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/Program.cs new file mode 100644 index 000000000000..d6601275a9ef --- /dev/null +++ b/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/Program.cs @@ -0,0 +1,29 @@ +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +builder.Services.AddControllers(); +// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi +// +builder.Services.AddOpenApi(options => +{ + options.OpenApiVersion = Microsoft.OpenApi.OpenApiSpecVersion.OpenApi3_0; +}); +// + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +// +if (app.Environment.IsDevelopment()) +{ + app.MapOpenApi("/openapi/{documentName}.yaml"); +} +// + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/TransformerJsonNode.cs b/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/TransformerJsonNode.cs new file mode 100644 index 000000000000..81d5c87c2ab3 --- /dev/null +++ b/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/TransformerJsonNode.cs @@ -0,0 +1,19 @@ +options.AddSchemaTransformer((schema, context, cancellationToken) => +{ + if (context.JsonTypeInfo.Type == typeof(WeatherForecast)) + { +- schema.Example = new OpenApiObject ++ schema.Example = new JsonObject + { +- ["date"] = new OpenApiString(DateTime.Now.AddDays(1).ToString("yyyy-MM-dd")), ++ ["date"] = DateTime.Now.AddDays(1).ToString("yyyy-MM-dd"), +- ["temperatureC"] = new OpenApiInteger(0), ++ ["temperatureC"] = 0, +- ["temperatureF"] = new OpenApiInteger(32), ++ ["temperatureF"] = 32, +- ["summary"] = new OpenApiString("Bracing"), ++ ["summary"] = "Bracing", + }; + } + return Task.CompletedTask; +}); diff --git a/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/WeatherForecast.cs b/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/WeatherForecast.cs new file mode 100644 index 000000000000..bbb212e825af --- /dev/null +++ b/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/WeatherForecast.cs @@ -0,0 +1,13 @@ +namespace WebAppOpenAPI10 +{ + public class WeatherForecast + { + public DateOnly Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string? Summary { get; set; } + } +} diff --git a/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/WebAppOpenAPI10.csproj b/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/WebAppOpenAPI10.csproj new file mode 100644 index 000000000000..bf00c497c4f4 --- /dev/null +++ b/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/WebAppOpenAPI10.csproj @@ -0,0 +1,18 @@ + + + + + net10.0 + enable + enable + true + + --openapi-version OpenApi3_0 + + + + + + + + diff --git a/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/WebAppOpenAPI10.http b/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/WebAppOpenAPI10.http new file mode 100644 index 000000000000..848dafa8e797 --- /dev/null +++ b/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/WebAppOpenAPI10.http @@ -0,0 +1,6 @@ +@WebAppOpenAPI10_HostAddress = http://localhost:5077 + +GET {{WebAppOpenAPI10_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/appsettings.Development.json b/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/appsettings.Development.json new file mode 100644 index 000000000000..0c208ae9181e --- /dev/null +++ b/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/appsettings.json b/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/appsettings.json new file mode 100644 index 000000000000..10f68b8c8b4f --- /dev/null +++ b/aspnetcore/release-notes/aspnetcore-10/samples/WebAppOpenAPI10/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +}