RicoSuter / NSwag

The Swagger/OpenAPI toolchain for .NET, ASP.NET Core and TypeScript.
http://NSwag.org
MIT License
6.69k stars 1.24k forks source link

C# Client - Properties are derived from sealed types #2696

Open redflowIT opened 4 years ago

redflowIT commented 4 years ago

HI all, I'm just start using Unchase OpenAPI (Swagger) Connected Service and I couldn't create any usable code because some properties are derived from sealed types. For example: 'Active': cannot derive from sealed type 'double'

This is the openAPI spec file I'm working on https://developers.pipedrive.com/docs/api/v1/pipedrive-api.yaml (without webhooks).

I'm almost sure I'm doing something wrong defining configuration. But I'm not able to understand what?

Any suggestions would be appreciated.

Thank you

RicoSuter commented 4 years ago

Can you post the code around the error?

redflowIT commented 4 years ago
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.1.5.0 (Newtonsoft.Json v11.0.0.0)")]
public partial class Archived_flag : double
{
    [Newtonsoft.Json.JsonConstructor]
    public Archived_flag()
        : base()
    {
    }

    private System.Collections.Generic.IDictionary<string, object> _additionalProperties = new System.Collections.Generic.Dictionary<string, object>();

    [Newtonsoft.Json.JsonExtensionData]
    public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
    {
        get { return _additionalProperties; }
        set { _additionalProperties = value; }
    }

}

Those are configuration I'm using: { "runtime": "WinX64", "defaultVariables": null, "documentGenerator": { "fromDocument": { "url": "C:\Users\domen\WorkSpace\PipeDrive\TestPipeDrive\pipedrive.yaml", "output": null } }, "codeGenerators": { "openApiToCSharpClient": { "clientBaseClass": null, "configurationClass": null, "generateClientClasses": true, "generateClientInterfaces": false, "injectHttpClient": false, "disposeHttpClient": false, "protectedMethods": [], "generateExceptionClasses": true, "exceptionClass": "ApiException", "wrapDtoExceptions": true, "useHttpClientCreationMethod": false, "httpClientType": "System.Net.Http.HttpClient", "useHttpRequestMessageCreationMethod": false, "useBaseUrl": true, "generateBaseUrlProperty": true, "generateSyncMethods": false, "exposeJsonSerializerSettings": true, "clientClassAccessModifier": "public", "typeAccessModifier": "public", "generateContractsOutput": true, "contractsNamespace": "PipeDrive.Net.API", "contractsOutputFilePath": "PipeDriveAPIContract.cs", "parameterDateTimeFormat": "s", "parameterDateFormat": "yyyy-MM-dd", "generateUpdateJsonSerializerSettingsMethod": true, "serializeTypeInformation": false, "queryNullValue": "", "className": "{controller}Client", "operationGenerationMode": "SingleClientFromPathSegments", "additionalNamespaceUsages": [], "additionalContractNamespaceUsages": [], "generateOptionalParameters": true, "generateJsonMethods": false, "enforceFlagEnums": false, "parameterArrayType": "System.Collections.Generic.IEnumerable", "parameterDictionaryType": "System.Collections.Generic.IDictionary", "responseArrayType": "System.Collections.Generic.ICollection", "responseDictionaryType": "System.Collections.Generic.IDictionary", "wrapResponses": false, "wrapResponseMethods": [], "generateResponseClasses": true, "responseClass": "SwaggerResponse", "namespace": "PipeDrive.Net.API", "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": "Record", "generateDefaultValues": true, "generateDataAnnotations": true, "excludedTypeNames": [], "excludedParameterNames": [], "handleReferences": false, "generateImmutableArrayProperties": false, "generateImmutableDictionaryProperties": false, "jsonSerializerSettingsTransformationMethod": null, "inlineNamedArrays": false, "inlineNamedDictionaries": false, "inlineNamedTuples": true, "inlineNamedAny": false, "generateDtoTypes": true, "generateOptionalPropertiesAsNullable": false, "templateDirectory": null, "typeNameGeneratorType": null, "propertyNameGeneratorType": null, "enumNameGeneratorType": null, "serviceHost": null, "serviceSchemes": null, "output": "PipeDriveAPI.cs" } } }

unchase commented 4 years ago

For example, (after deleting webhooks from this yaml) NSwag.Commands generates this:

Screenshot: fail

Code:

    [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.1.5.0 (Newtonsoft.Json v12.0.0.2)")]
    public partial class NumberBooleanDefault0 : double
    {
        private System.Collections.Generic.IDictionary<string, object> _additionalProperties = new System.Collections.Generic.Dictionary<string, object>();

        [Newtonsoft.Json.JsonExtensionData]
        public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
        {
            get { return _additionalProperties; }
            set { _additionalProperties = value; }
        }
    }

For this part of yaml-file:

    NumberBoolean:
      type: number
      enum:
        - 0
        - 1
    NumberBooleanDefault0:
      allOf:
        - $ref: '#/components/schemas/NumberBoolean'
        - type: number
          default: 0
    NumberBooleanDefault1:
      allOf:
        - $ref: '#/components/schemas/NumberBoolean'
        - type: number
          default: 1
Lyra2108 commented 4 years ago

I have had the same problem the issue is the type declaration.

The YAML above is struggling with the all of type indentation: The following would work:

    NumberBoolean:
      type: number

    NumberBooleanDefault0:
      allOf:
        - $ref: '#/components/schemas/NumberBoolean'
      type: number
      default: 0

The bug in NSwag seems to be that it is not checking the type from an allOf but expecting that it is always set directly.

RicoSuter commented 4 years ago

I think if you'd use oneOf instead of allOf it would work, can you confirm?

mathmul commented 1 year ago

With

<PackageReference Include="NSwag.MSBuild" Version="13.16.1">

this

            payment_overdue_date_utc:
              oneOf:
                - $ref: '#/components/schemas/DateTimeUtc'
                - description: 'Order must be paid by this date.'

used to work fine, although I suppose allOf would be more appropriate.

But now with

<PackageReference Include="NSwag.MSBuild" Version="13.18.2">

it produces error on dotnet build:

Path\To\Api\Client.cs(9087,53): error CS0509: 'Payment_overdue_date_utc': cannot derive from sealed type 'DateTimeOffset' [Path\To\Api\Api.csproj]

The reference is

components:
  schemas:
    DateTimeUtc:
      type: string
      format: date-time
      nullable: true
      example: '2020-09-25T08:15:30+00:00'

I also tried

            payment_overdue_date_utc:
              oneOf:
                - $ref: '#/components/schemas/DateTimeUtc'
                - description: 'Order must be paid by this date.'

            payment_overdue_date_utc:
              allOf:
                - $ref: '#/components/schemas/DateTimeUtc'
                - description: 'Order must be paid by this date.'

            payment_overdue_date_utc:
              $ref: '#/components/schemas/DateTimeUtc'
              description: 'Order must be paid by this date.'

            payment_overdue_date_utc:
              type: string
              format: date-time
              nullable: true
              example: '2020-09-25T08:15:30+00:00'
              description: 'Order must be paid by this date.'

csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
    <PackageReference Include="NSwag.MSBuild" Version="13.18.2">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
  </ItemGroup>

  <Target Name="NSwag" AfterTargets="Build">
    <Exec Command="$(NSwagExe_Net60) openapi2csclient /classname:Client /namespace:Api /input:swagger.yml /output:Client.cs /generateClientInterfaces:true /usebaseurl:false" />
  </Target>

</Project>