Skip to content

Commit 21acf10

Browse files
Prepare for .NET 10 preview 4 (#3388)
Cherry-pick changes from #3386 to prepare for ASP.NET Core 10 preview 4 and Microsoft.OpenApi 2.0.0-preview.17.
1 parent 5cdb231 commit 21acf10

31 files changed

+281
-179
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[Oo]bj/
22
[Bb]in/
3+
.dotnet/
34
.vs/
45
.idea*
56
BenchmarkDotNet.Artifacts*/

Directory.Build.props

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
44
<Authors>domaindrivendev</Authors>
55
<!-- HACK See https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/2893 -->
6-
<BuildInParallel>false</BuildInParallel>
6+
<BuildInParallel Condition="$([System.OperatingSystem]::IsWindows())">false</BuildInParallel>
77
<ChecksumAlgorithm>SHA256</ChecksumAlgorithm>
88
<Company>https://github.com/domaindrivendev/Swashbuckle.AspNetCore</Company>
99
<ContinuousIntegrationBuild Condition=" '$(CI)' != '' ">true</ContinuousIntegrationBuild>

Directory.Packages.props

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<PackageVersion Include="IdentityServer4" Version="3.1.4" />
88
<PackageVersion Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
99
<PackageVersion Include="JunitXml.TestLogger" Version="6.1.0" />
10+
<PackageVersion Include="MartinCostello.Logging.XUnit.v3" Version="0.5.1" />
1011
<PackageVersion Include="Microsoft.AspNetCore" Version="2.3.0" />
1112
<PackageVersion Include="Microsoft.AspNetCore.Mvc.ApiExplorer" Version="2.3.0" />
1213
<PackageVersion Include="Microsoft.AspNetCore.Mvc.DataAnnotations" Version="2.3.0" />

README.md

+79-61
Original file line numberDiff line numberDiff line change
@@ -197,67 +197,84 @@ These packages are provided by the open-source community.
197197

198198
The steps described above will get you up and running with minimal setup. However, Swashbuckle offers a lot of flexibility to customize as you see fit. Check out the table below for the full list of options:
199199

200-
* [Swashbuckle.AspNetCore.Swagger](#swashbuckleaspnetcoreswagger)
201-
202-
* [Change the Path for Swagger JSON Endpoints](#change-the-path-for-swagger-json-endpoints)
203-
* [Modify Swagger with Request Context](#modify-swagger-with-request-context)
204-
* [Serialize Swagger JSON in the 2.0 format](#serialize-swagger-in-the-20-format)
205-
* [Working with Virtual Directories and Reverse Proxies](#working-with-virtual-directories-and-reverse-proxies)
206-
* [Customizing how the OpenAPI document is serialized](#customizing-how-the-openapi-document-is-serialized)
207-
208-
* [Swashbuckle.AspNetCore.SwaggerGen](#swashbuckleaspnetcoreswaggergen)
209-
210-
* [Assign Explicit OperationIds](#assign-explicit-operationids)
211-
* [List Operations Responses](#list-operation-responses)
212-
* [Flag Required Parameters and Schema Properties](#flag-required-parameters-and-schema-properties)
213-
* [Handle Forms and File Uploads](#handle-forms-and-file-uploads)
214-
* [Handle File Downloads](#handle-file-downloads)
215-
* [Include Descriptions from XML Comments](#include-descriptions-from-xml-comments)
216-
* [Provide Global API Metadata](#provide-global-api-metadata)
217-
* [Generate Multiple Swagger Documents](#generate-multiple-swagger-documents)
218-
* [Omit Obsolete Operations and/or Schema Properties](#omit-obsolete-operations-andor-schema-properties)
219-
* [Omit Arbitrary Operations](#omit-arbitrary-operations)
220-
* [Customize Operation Tags (e.g. for UI Grouping)](#customize-operation-tags-eg-for-ui-grouping)
221-
* [Change Operation Sort Order (e.g. for UI Sorting)](#change-operation-sort-order-eg-for-ui-sorting)
222-
* [Customize Schema Id's](#customize-schema-ids)
223-
* [Override Schema for Specific Types](#override-schema-for-specific-types)
224-
* [Extend Generator with Operation, Schema & Document Filters](#extend-generator-with-operation-schema--document-filters)
225-
* [Add Security Definitions and Requirements](#add-security-definitions-and-requirements)
226-
* [Add Security Definitions and Requirements for Bearer auth](#add-security-definitions-and-requirements-for-bearer-auth)
227-
* [Inheritance and Polymorphism](#inheritance-and-polymorphism)
228-
229-
* [Swashbuckle.AspNetCore.SwaggerUI](#swashbuckleaspnetcoreswaggerui)
230-
* [Change Relative Path to the UI](#change-relative-path-to-the-ui)
231-
* [Change Document Title](#change-document-title)
232-
* [Change CSS or JS Paths](#change-css-or-js-paths)
233-
* [List Multiple Swagger Documents](#list-multiple-swagger-documents)
234-
* [Apply swagger-ui Parameters](#apply-swagger-ui-parameters)
235-
* [Inject Custom JavaScript](#inject-custom-javascript)
236-
* [Inject Custom CSS](#inject-custom-css)
237-
* [Customize index.html](#customize-indexhtml)
238-
* [Enable OAuth2.0 Flows](#enable-oauth20-flows)
239-
* [Use client-side request and response interceptors](#use-client-side-request-and-response-interceptors)
240-
241-
* [Swashbuckle.AspNetCore.Annotations](#swashbuckleaspnetcoreannotations)
242-
* [Install and Enable Annotations](#install-and-enable-annotations)
243-
* [Enrich Operation Metadata](#enrich-operation-metadata)
244-
* [Enrich Response Metadata](#enrich-response-metadata)
245-
* [Enrich Parameter Metadata](#enrich-parameter-metadata)
246-
* [Enrich RequestBody Metadata](#enrich-requestbody-metadata)
247-
* [Enrich Schema Metadata](#enrich-schema-metadata)
248-
* [Apply Schema Filters to Specific Types](#apply-schema-filters-to-specific-types)
249-
* [Add Tag Metadata](#add-tag-metadata)
250-
251-
* [Swashbuckle.AspNetCore.Cli](#swashbuckleaspnetcorecli)
252-
* [Retrieve Swagger Directly from a Startup Assembly](#retrieve-swagger-directly-from-a-startup-assembly)
253-
* [Use the CLI Tool with a Custom Host Configuration](#use-the-cli-tool-with-a-custom-host-configuration)
254-
255-
* [Swashbuckle.AspNetCore.ReDoc](#swashbuckleaspnetcoreredoc)
256-
* [Change Relative Path to the UI](#redoc-change-relative-path-to-the-ui)
257-
* [Change Document Title](#redoc-change-document-title)
258-
* [Apply Redoc Parameters](#apply-redoc-parameters)
259-
* [Inject Custom CSS](#redoc-inject-custom-css)
260-
* [Customize index.html](#redoc-customize-indexhtml)
200+
- [Swashbuckle.AspNetCore](#swashbuckleaspnetcore)
201+
- [Compatibility](#compatibility)
202+
- [Getting Started](#getting-started)
203+
- [System.Text.Json (STJ) vs Newtonsoft](#systemtextjson-stj-vs-newtonsoft)
204+
- [Swashbuckle, ApiExplorer, and Routing](#swashbuckle-apiexplorer-and-routing)
205+
- [Components](#components)
206+
- ["Core" Packages (i.e. installed via Swashbuckle.AspNetCore)](#core-packages-ie-installed-via-swashbuckleaspnetcore)
207+
- [Additional Packages](#additional-packages)
208+
- [Community Packages](#community-packages)
209+
- [Configuration \& Customization](#configuration--customization)
210+
- [Swashbuckle.AspNetCore.Swagger](#swashbuckleaspnetcoreswagger)
211+
- [Change the Path for Swagger JSON Endpoints](#change-the-path-for-swagger-json-endpoints)
212+
- [Modify Swagger with Request Context](#modify-swagger-with-request-context)
213+
- [Serialize Swagger in the 2.0 format](#serialize-swagger-in-the-20-format)
214+
- [Working with Virtual Directories and Reverse Proxies](#working-with-virtual-directories-and-reverse-proxies)
215+
- [Customizing how the OpenAPI document is serialized](#customizing-how-the-openapi-document-is-serialized)
216+
- [Swashbuckle.AspNetCore.SwaggerGen](#swashbuckleaspnetcoreswaggergen)
217+
- [Assign Explicit OperationIds](#assign-explicit-operationids)
218+
- [List Operation Responses](#list-operation-responses)
219+
- [Explicit Responses](#explicit-responses)
220+
- [Flag Required Parameters and Schema Properties](#flag-required-parameters-and-schema-properties)
221+
- [Handle Forms and File Uploads](#handle-forms-and-file-uploads)
222+
- [Handle File Downloads](#handle-file-downloads)
223+
- [Include Descriptions from XML Comments](#include-descriptions-from-xml-comments)
224+
- [Provide Global API Metadata](#provide-global-api-metadata)
225+
- [Generate Multiple Swagger Documents](#generate-multiple-swagger-documents)
226+
- [Decorate Individual Actions](#decorate-individual-actions)
227+
- [Assign Actions to Documents by Convention](#assign-actions-to-documents-by-convention)
228+
- [Customize the Action Selection Process](#customize-the-action-selection-process)
229+
- [Exposing Multiple Documents through the UI](#exposing-multiple-documents-through-the-ui)
230+
- [Omit Obsolete Operations and/or Schema Properties](#omit-obsolete-operations-andor-schema-properties)
231+
- [Omit Arbitrary Operations](#omit-arbitrary-operations)
232+
- [Decorate Individual Actions](#decorate-individual-actions-1)
233+
- [Omit Actions by Convention](#omit-actions-by-convention)
234+
- [Customize Operation Tags (e.g. for UI Grouping)](#customize-operation-tags-eg-for-ui-grouping)
235+
- [Change Operation Sort Order (e.g. for UI Sorting)](#change-operation-sort-order-eg-for-ui-sorting)
236+
- [Customize Schema Id's](#customize-schema-ids)
237+
- [Override Schema for Specific Types](#override-schema-for-specific-types)
238+
- [Extend Generator with Operation, Schema \& Document Filters](#extend-generator-with-operation-schema--document-filters)
239+
- [Operation Filters](#operation-filters)
240+
- [Schema Filters](#schema-filters)
241+
- [Document Filters](#document-filters)
242+
- [Add Security Definitions and Requirements](#add-security-definitions-and-requirements)
243+
- [Add Security Definitions and Requirements for Bearer auth](#add-security-definitions-and-requirements-for-bearer-auth)
244+
- [Inheritance and Polymorphism](#inheritance-and-polymorphism)
245+
- [Enabling Inheritance](#enabling-inheritance)
246+
- [Enabling Polymorphism](#enabling-polymorphism)
247+
- [Detecting Subtypes](#detecting-subtypes)
248+
- [Describing Discriminators](#describing-discriminators)
249+
- [Swashbuckle.AspNetCore.SwaggerUI](#swashbuckleaspnetcoreswaggerui)
250+
- [Change Relative Path to the UI](#change-relative-path-to-the-ui)
251+
- [Change Document Title](#change-document-title)
252+
- [Change CSS or JS Paths](#change-css-or-js-paths)
253+
- [List Multiple Swagger Documents](#list-multiple-swagger-documents)
254+
- [Apply swagger-ui Parameters](#apply-swagger-ui-parameters)
255+
- [Inject Custom JavaScript](#inject-custom-javascript)
256+
- [Inject Custom CSS](#inject-custom-css)
257+
- [Customize index.html](#customize-indexhtml)
258+
- [Enable OAuth2.0 Flows](#enable-oauth20-flows)
259+
- [Use client-side request and response interceptors](#use-client-side-request-and-response-interceptors)
260+
- [Swashbuckle.AspNetCore.Annotations](#swashbuckleaspnetcoreannotations)
261+
- [Install and Enable Annotations](#install-and-enable-annotations)
262+
- [Enrich Operation Metadata](#enrich-operation-metadata)
263+
- [Enrich Response Metadata](#enrich-response-metadata)
264+
- [Enrich Parameter Metadata](#enrich-parameter-metadata)
265+
- [Enrich RequestBody Metadata](#enrich-requestbody-metadata)
266+
- [Enrich Schema Metadata](#enrich-schema-metadata)
267+
- [Apply Schema Filters to Specific Types](#apply-schema-filters-to-specific-types)
268+
- [Add Tag Metadata](#add-tag-metadata)
269+
- [List Known Subtypes for Inheritance and Polymorphism](#list-known-subtypes-for-inheritance-and-polymorphism)
270+
- [Enrich Polymorphic Base Classes with Discriminator Metadata](#enrich-polymorphic-base-classes-with-discriminator-metadata)
271+
- [Swashbuckle.AspNetCore.Cli](#swashbuckleaspnetcorecli)
272+
- [Retrieve Swagger Directly from a Startup Assembly](#retrieve-swagger-directly-from-a-startup-assembly)
273+
- [Using the tool with the .NET SDK](#using-the-tool-with-the-net-sdk)
274+
- [Using the tool with the .NET 6.0 SDK or later](#using-the-tool-with-the-net-60-sdk-or-later)
275+
- [Use the CLI Tool with a Custom Host Configuration](#use-the-cli-tool-with-a-custom-host-configuration)
276+
- [Swashbuckle.AspNetCore.ReDoc](#swashbuckleaspnetcoreredoc)
277+
- [Apply Redoc Parameters](#apply-redoc-parameters)
261278

262279
## Swashbuckle.AspNetCore.Swagger ##
263280

@@ -895,6 +912,7 @@ public class AutoRestSchemaFilter : ISchemaFilter
895912
var type = context.Type;
896913
if (type.IsEnum)
897914
{
915+
schema.Extensions ??= [];
898916
schema.Extensions.Add(
899917
"x-ms-enum",
900918
new OpenApiObject

global.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"sdk": {
33
"version": "10.0.100-preview.3.25201.16",
44
"allowPrerelease": false,
5-
"rollForward": "latestMajor"
5+
"rollForward": "latestMajor",
6+
"paths": [ ".dotnet", "$host$" ]
67
}
78
}

src/Swashbuckle.AspNetCore.Annotations/AnnotationsOperationFilter.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -116,17 +116,18 @@ private static void ApplySwaggerResponseAttributes(
116116

117117
operation.Responses[statusCode] = response;
118118

119-
if (swaggerResponseAttribute.ContentTypes is { } contentTypes)
119+
if (response is OpenApiResponse concrete &&
120+
swaggerResponseAttribute.ContentTypes is { } contentTypes)
120121
{
121-
response.Content.Clear();
122+
concrete.Content?.Clear();
122123

123124
foreach (var contentType in contentTypes)
124125
{
125126
var schema = (swaggerResponseAttribute.Type != null && swaggerResponseAttribute.Type != typeof(void))
126127
? context.SchemaGenerator.GenerateSchema(swaggerResponseAttribute.Type, context.SchemaRepository)
127128
: null;
128129

129-
response.Content.Add(contentType, new OpenApiMediaType { Schema = schema });
130+
concrete.Content.Add(contentType, new OpenApiMediaType { Schema = schema });
130131
}
131132
}
132133
}

src/Swashbuckle.AspNetCore.ApiTesting/ApiTestRunnerBase.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public async Task TestAsync(
5252
{
5353
var openApiDocument = _options.GetOpenApiDocument(documentName);
5454

55-
if (!openApiDocument.TryFindOperationById(operationId, out string pathTemplate, out OperationType operationType))
55+
if (!openApiDocument.TryFindOperationById(operationId, out string pathTemplate, out var operationType))
5656
{
5757
throw new InvalidOperationException($"Operation with id '{operationId}' not found in OpenAPI document '{documentName}'");
5858
}

src/Swashbuckle.AspNetCore.ApiTesting/JsonValidation/JsonNumberValidator.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public bool Validate(
2424
var errors = new List<string>();
2525

2626
// multipleOf
27-
if (schema.MultipleOf is { } multipleOf && ((numberValue % multipleOf) != 0))
27+
if (schema.MultipleOf is { } multipleOf && (numberValue % multipleOf) != 0)
2828
{
2929
errors.Add($"Path: {instance.Path}. Number is not evenly divisible by multipleOf");
3030
}

src/Swashbuckle.AspNetCore.ApiTesting/OpenApiDocumentExtensions.cs

+14-8
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,23 @@ internal static bool TryFindOperationById(
1111
out string pathTemplate,
1212
out OperationType operationType)
1313
{
14-
foreach (var pathEntry in openApiDocument.Paths ?? [])
14+
if (openApiDocument.Paths is { Count: > 0 } paths)
1515
{
16-
var pathItem = pathEntry.Value;
17-
18-
foreach (var operationEntry in pathItem.Operations)
16+
foreach (var pathEntry in paths)
1917
{
20-
if (operationEntry.Value.OperationId == operationId)
18+
var pathItem = pathEntry.Value;
19+
20+
if (pathItem.Operations is { Count: > 0 } operations)
2121
{
22-
pathTemplate = pathEntry.Key;
23-
operationType = operationEntry.Key;
24-
return true;
22+
foreach (var operation in operations)
23+
{
24+
if (operation.Value.OperationId == operationId)
25+
{
26+
pathTemplate = pathEntry.Key;
27+
operationType = operation.Key;
28+
return true;
29+
}
30+
}
2531
}
2632
}
2733
}

src/Swashbuckle.AspNetCore.ApiTesting/RequestValidator.cs

+11-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,17 @@ public void Validate(
1919
OperationType operationType)
2020
{
2121
var operationSpec = openApiDocument.GetOperationByPathAndType(pathTemplate, operationType, out var pathSpec);
22-
IOpenApiParameter[] parameterSpecs = [.. pathSpec.Parameters, .. operationSpec.Parameters];
22+
IOpenApiParameter[] parameterSpecs = [];
23+
24+
if (pathSpec.Parameters is { Count: > 0 } pathParameters)
25+
{
26+
parameterSpecs = [.. parameterSpecs, .. pathParameters];
27+
}
28+
29+
if (operationSpec.Parameters is { Count: > 0 } operationParameters)
30+
{
31+
parameterSpecs = [.. parameterSpecs, .. operationParameters];
32+
}
2333

2434
// Convert to absolute Uri as a workaround to limitation with Uri class - i.e. most of it's methods are not supported for relative Uri's.
2535
var requestUri = new Uri(new Uri("http://tempuri.org"), request.RequestUri);

src/Swashbuckle.AspNetCore.ApiTesting/ResponseValidator.cs

+5
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ private static void ValidateHeaders(
3939
IDictionary<string, IOpenApiHeader> headerSpecs,
4040
NameValueCollection headerValues)
4141
{
42+
if (headerSpecs is null)
43+
{
44+
return;
45+
}
46+
4247
foreach (var entry in headerSpecs)
4348
{
4449
var value = headerValues[entry.Key];

src/Swashbuckle.AspNetCore.SwaggerGen/DependencyInjection/SwaggerGenOptionsExtensions.cs

-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ public static void DescribeAllParametersInCamelCase(this SwaggerGenOptions swagg
126126
swaggerGenOptions.SwaggerGeneratorOptions.DescribeAllParametersInCamelCase = true;
127127
}
128128

129-
130129
/// <summary>
131130
/// Provide specific server information to include in the generated Swagger document
132131
/// </summary>

src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.ComponentModel;
22
using System.ComponentModel.DataAnnotations;
3+
using System.Globalization;
34
using Microsoft.AspNetCore.Mvc.ApiExplorer;
45
using Microsoft.AspNetCore.Routing.Constraints;
56
using Microsoft.OpenApi.Models;
@@ -155,12 +156,15 @@ private static void ApplyRouteConstraints(OpenApiSchema schema, ApiParameterRout
155156
return definitionSchema.ResolveType(schemaRepository);
156157
}
157158

158-
foreach (var subSchema in schema.AllOf)
159+
if (schema.AllOf is { Count: > 0 } allOf)
159160
{
160-
var type = subSchema.ResolveType(schemaRepository);
161-
if (type != null)
161+
foreach (var subSchema in allOf)
162162
{
163-
return type;
163+
var type = subSchema.ResolveType(schemaRepository);
164+
if (type != null)
165+
{
166+
return type;
167+
}
164168
}
165169
}
166170

src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/SchemaGenerator.cs

+2
Original file line numberDiff line numberDiff line change
@@ -420,10 +420,12 @@ private OpenApiSchema CreateObjectSchema(DataContract dataContract, SchemaReposi
420420
if (_generatorOptions.UseAllOfForInheritance)
421421
{
422422
root = new OpenApiSchema();
423+
root.AllOf ??= [];
423424
root.AllOf.Add(baseTypeSchema);
424425
}
425426
else
426427
{
428+
schema.AllOf ??= [];
427429
schema.AllOf.Add(baseTypeSchema);
428430
}
429431

0 commit comments

Comments
 (0)