-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Closed
Description
Describe the bug
The order of optional params in generated dotnet client added via OperationProcessor is invalid, as they should be added after all required params. Error CS1737
Version of NSwag toolchain, computer and .NET runtime used
Dotnet 9, NSwag v14.3.0 (there's no issue in v14.2.0)
To Reproduce
OperationProcessor
public sealed class TestOptionalParamOperationProcessor : IOperationProcessor
{
public bool Process(OperationProcessorContext context)
{
context.OperationDescription.Operation.Parameters.Add(
new OpenApiParameter
{
Description =
"Optional param",
Schema = new OpenApiHeader
{
Default = null,
IsNullableRaw = false,
Type = JsonObjectType.String,
AllowEmptyValue = true
},
Kind = OpenApiParameterKind.Header,
Name = "x-test-optional-parameter",
OriginalName = "optionalParam"
});
return true;
}
}
Controller
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries =
[
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
];
[HttpGet("{cityId:guid}")]
public WeatherForecast GetById(Guid cityId) => new()
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(1)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)],
CityId = cityId
};
}
Configuration in Program.cs
...
builder.Services.AddOpenApiDocument(config =>
{
config.Title = "My API";
config.Version = "v1";
config.DocumentName = "test";
config.OperationProcessors.Add(new TestOptionalParamOperationProcessor());
});
...
WebApi.csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.3"/>
<PackageReference Include="NSwag.AspNetCore" Version="14.3.0" />
<PackageReference Include="NSwag.MSBuild" Version="14.3.0" PrivateAssets="All" />
</ItemGroup>
<PropertyGroup>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
</PropertyGroup>
<Target Name="NSwag" AfterTargets="PostBuildEvent" Condition=" '$(Configuration)' == 'Debug' ">
<Exec WorkingDirectory="$(ProjectDir)" EnvironmentVariables="ASPNETCORE_ENVIRONMENT=Development" Command="$(NSwagExe_Net90) run nswag.json /variables:Configuration=$(Configuration)" />
</Target>
</Project>
nswag.json
{
"runtime": "Net90",
"defaultVariables": null,
"documentGenerator": {
"aspNetCoreToOpenApi": {
"project": "web-api.csproj",
"documentName": "test",
"msBuildProjectExtensionsPath": null,
"configuration": null,
"runtime": null,
"targetFramework": null,
"noBuild": true,
"msBuildOutputPath": null,
"verbose": true,
"workingDirectory": null,
"aspNetCoreEnvironment": null,
"output": "openapi-test.json",
"newLineBehavior": "Auto"
}
},
"codeGenerators": {
"openApiToCSharpClient": {
"clientBaseClass": null,
"configurationClass": null,
"generateClientClasses": true,
"suppressClientClassesOutput": false,
"generateClientInterfaces": true,
"suppressClientInterfacesOutput": false,
"clientBaseInterface": null,
"injectHttpClient": true,
"disposeHttpClient": false,
"protectedMethods": [],
"generateExceptionClasses": true,
"exceptionClass": "ApiException",
"wrapDtoExceptions": true,
"useHttpClientCreationMethod": false,
"httpClientType": "System.Net.Http.HttpClient",
"useHttpRequestMessageCreationMethod": false,
"useBaseUrl": false,
"generateBaseUrlProperty": false,
"generateSyncMethods": false,
"generatePrepareRequestAndProcessResponseAsAsyncMethods": false,
"exposeJsonSerializerSettings": false,
"clientClassAccessModifier": "public",
"typeAccessModifier": "public",
"propertySetterAccessModifier": "",
"generateNativeRecords": false,
"generateContractsOutput": false,
"contractsNamespace": null,
"contractsOutputFilePath": null,
"parameterDateTimeFormat": "s",
"parameterDateFormat": "yyyy-MM-dd",
"generateUpdateJsonSerializerSettingsMethod": true,
"useRequestAndResponseSerializationSettings": false,
"serializeTypeInformation": false,
"queryNullValue": "",
"className": "{controller}Api",
"operationGenerationMode": "MultipleClientsFromOperationId",
"additionalNamespaceUsages": null,
"additionalContractNamespaceUsages": [],
"generateOptionalParameters": true,
"generateJsonMethods": false,
"enforceFlagEnums": false,
"parameterArrayType": "IEnumerable",
"parameterDictionaryType": "IDictionary",
"responseArrayType": "List",
"responseDictionaryType": "Dictionary",
"wrapResponses": false,
"wrapResponseMethods": [],
"generateResponseClasses": false,
"responseClass": "SwaggerResponse",
"namespace": "Test.Api.Client",
"requiredPropertiesMustBeDefined": true,
"dateType": "System.DateTimeOffset",
"jsonConverters": null,
"anyType": "object",
"dateTimeType": "System.DateTimeOffset",
"timeType": "System.TimeSpan",
"timeSpanType": "System.TimeSpan",
"arrayType": "System.Collections.Generic.ICollection",
"arrayInstanceType": "System.Collections.ObjectModel.Collection",
"dictionaryType": "System.Collections.Generic.IDictionary",
"dictionaryInstanceType": "System.Collections.Generic.Dictionary",
"arrayBaseType": "System.Collections.ObjectModel.Collection",
"dictionaryBaseType": "System.Collections.Generic.Dictionary",
"classStyle": "Poco",
"jsonLibrary": "SystemTextJson",
"generateDefaultValues": true,
"generateDataAnnotations": true,
"excludedTypeNames": [],
"excludedParameterNames": [
""
],
"handleReferences": false,
"generateImmutableArrayProperties": false,
"generateImmutableDictionaryProperties": false,
"jsonSerializerSettingsTransformationMethod": "JsonSerializerHelper.ConfigureOptions",
"inlineNamedArrays": false,
"inlineNamedDictionaries": false,
"inlineNamedTuples": true,
"inlineNamedAny": false,
"generateDtoTypes": false,
"generateOptionalPropertiesAsNullable": false,
"generateNullableReferenceTypes": false,
"templateDirectory": null,
"serviceHost": null,
"serviceSchemes": null,
"output": "ApiClient.cs",
"newLineBehavior": "Auto"
}
}
}
Additional context
It's just working totally fine when switching to NSwag 14.2.0.
Expected behavior
AS IS:
public partial interface IWeatherForecastApi
{
System.Threading.Tasks.Task<WeatherForecast> GetByIdAsync(string optionalParam = null, System.Guid cityId, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken));
}
TO BE:
public partial interface IWeatherForecastApi
{
System.Threading.Tasks.Task<WeatherForecast> GetByIdAsync(System.Guid cityId, string optionalParam = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken));
}
xC0dex, djonesz, msrouchou, andrew-potachits, MichaCo and 6 more
Metadata
Metadata
Assignees
Labels
No labels