RicoSuter/NSwag

Dictionary type mapping issue in .net 8

Closed this issue · 1 comments

First time reporting an issue, if I step wrong, please let me know.

I am upgrading projects to .net 8 from .net 7. Using NSwag 14.1.0

In my service layer I have a model being returned with the following definition:

public Dictionary<PageSize, WidgetLocation> Location { get; set; }

PageSize is an enum
WidgetLocation is a class

OpenAPI Reference:

<OpenApiReference Include="OpenAPIs\Query.UI.json" CodeGenerator="NSwagCSharp" Namespace="IML.Core.ServiceClients.Query.UI" Options="/OperationGenerationMode:MultipleClientsFromOperationId /GenerateClientInterfaces:true  /AdditionalNamespaceUsages:IML.Core.ServiceClients.Query,System /GenerateUpdateJsonSerializerSettingsMethod:false /ClientBaseClass:NSwagBase /DateTimeType:DateTime" ClassName="UIClient">
      <SourceUri>http://localhost:8085/swagger/v1/swagger.json</SourceUri>
    </OpenApiReference>

Here is what the generated stuff looks like:

        /// <summary>
        /// Gets or sets the dictionary of widget locations for different page sizes.
        /// </summary>
        [Newtonsoft.Json.JsonProperty("location", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
        public Location Location { get; set; }

        /// <summary>
        /// Gets or sets the dictionary of selected options for the widget.
        /// </summary>
        [Newtonsoft.Json.JsonProperty("selectedOptions", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
        public System.Collections.Generic.IDictionary<string, string> SelectedOptions { get; set; }

You can see a dictionary value named SelectedOptions that works fine of type Dictionary<string, string>

I've attempted a number of fixes. However, anything I do seems to fail in one way or another.

Based on chat gpt's recommendation I attempted to add a type mapping to resolve it like so:

{
  "runtime": "Net80",
  "documentGenerator": {
    "fromDocument": {
      "url": "http://localhost:8085/swagger/v1/swagger.json"
    }
  },
  "codeGenerators": {
    "openApiToCSharpClient": {
      "className": "UIClient",
      "namespace": "IML.Core.ServiceClients.Query.UI",
      "clientBaseClass": "NSwagBase",
      "generateClientInterfaces": true,
      "operationGenerationMode": "MultipleClientsFromOperationId",
      "additionalNamespaceUsages": [
        "IML.Core.ServiceClients.Query",
        "System"
      ],
      "generateUpdateJsonSerializerSettingsMethod": false,
      "dateTimeType": "DateTime",
      "typeMappings": {
        "Location": "System.Collections.Generic.Dictionary<PageSize, WidgetLocation>"
      }
    }
  }
}

Doing so outputs this error immediately:

MSB3073	The command "dotnet --roll-forward-on-no-candidate-fx 2 "C:\Users\cjchambers\.nuget\packages\nswag.msbuild\14.1.0\buildTransitive\../tools/Net80//dotnet-nswag.dll" openapi2csclient /className:UIClient /namespace:IML.Core.ServiceClients.Query.UI /generateExceptionClasses:false /input:"D:\GITWorkspace\Libraries\IML.Core\IML.Core.ServiceClients.Query\OpenAPIs\Query.UI.json" /output:"D:\GITWorkspace\Libraries\IML.Core\IML.Core.ServiceClients.Query\obj\Query.UIClient.cs" D:\GITWorkspace\Libraries\IML.Core\IML.Core.ServiceClients.Query\UI.json /generateResponseClasses:false" exited with code -1.	IML.Core.ServiceClients.Query	C:\Users\cjchambers\.nuget\packages\nswag.apidescription.client\14.1.0\build\NSwag.ApiDescription.Client.targets	285	

Which is interesting because when I started this, the first problem I had to resolve was that "/generateExceptionClasses:false" was throwing an error. Including it results in failure.

So based on AI advice I attempted to customize the generation with this:

  <Target Name="CustomNSwagGeneration" BeforeTargets="Build">
    <!-- Custom NSwag command -->
    <Exec Command='dotnet --roll-forward-on-no-candidate-fx 2 "$(MSBuildThisFileDirectory)nswag.json" openapi2csclient /input:"$(MSBuildThisFileDirectory)OpenAPIs\Query.UI.json" /output:"$(MSBuildThisFileDirectory)obj\Query.UIClient.cs"' />
  </Target>

But this gave me the same error.

FYI.

I managed to resolve this. It was due to the API having a reference to Swashbuckle.AspNetCore 6.7.0 (recently upgraded as part of .net 8 upgrade) - setting up a new project revealed this worked just fine with the version that comes standard (6.4.0)

So for anyone else experiencing issues, that was my resolution.