Nswag: The abstract class cannot be instantiated.

Created on 23 Nov 2018  Â·  20Comments  Â·  Source: RicoSuter/NSwag

Hi,

I read this post: https://github.com/RSuter/NSwag/issues/1652 and I added a comment but my issue is not exactly the same even if the error is the same :).

So here is my code:

    public class GroupedResultDto<IItemDto, TEntity> : GroupedResultDto<IItemDto, TEntity, Guid>
        where TEntity : IEntityDto
    {
    }

    public class GroupedResultDto<IItemDto, TEntity, TPrimaryKey>
        where TEntity : IEntityDto<TPrimaryKey>
    {
        public int TotalCount { get; set; }
        public IEnumerable<GroupItemDto<IItemDto, TEntity, TPrimaryKey>> GroupItems { get; set; }
        public bool HasNext { get; set; }
    }
public class GroupItemDto<IItemDto, TEntity> : GroupItemDto<IItemDto, TEntity, Guid>
        where TEntity : IEntityDto
    {
    }

    public class GroupItemDto<IItemDto, TEntity, TPrimaryKey>
        where TEntity : IEntityDto<TPrimaryKey>
    {
        public IItemDto Item { get; set; }
        public IEnumerable<TEntity> Items { get; set; }
    }

```
public interface IItemDto
{
string Discriminator { get; }
}


  ```
  [JsonConverter(typeof(JsonInheritanceConverter))]
    [KnownType(typeof(ItemDto<string>))]
    [KnownType(typeof(ItemDto<UserDto>))]
    [KnownType(typeof(ItemDto<NotificationDto>))]
    public class ItemDto<T> : IItemDto
        where T : IComparable
    {
        public T Key { get; set; }
        public string Discriminator
        {
            get
            {
                return typeof(T).Name;
            }
        }

        public int CompareTo(object obj)
        {
            if (!(obj is ItemDto<T> item))
            {
                throw new InvalidCastException($"Not able to cast as '{typeof(T).Name}'.");
            }
            return Key.CompareTo(item.Key);
        }
    }

As Discriminator property is already declared in Interface IItemDto, so I updated your JsonInheritance converter like this:

  public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            try
            {
                _isWriting = true;

                var jObject = JObject.FromObject(value, serializer);
                //jObject[_discriminator] = JToken.FromObject(GetDiscriminatorValue(value.GetType()));
                writer.WriteToken(jObject.CreateReader());
            }
            finally
            {
                _isWriting = false;
            }
        }

As I read in your documentation (https://github.com/RSuter/NJsonSchema/wiki/Inheritance), I updated nswagstudio like this:
image

image

But each time I try to get a groupedResultDto, I continue to have this error:

The abstract class 'IItemDto' cannot be instantiated.

Could you help me? Let me know if you need more details.

An thanks a lot for your work! Your app is really useful!

await-retest done bug

Most helpful comment

Hi @ranouf / @RSuter any updates on this? In a perfect world I would like to use interfaces and not abstract classes as proposed.

Add to this, Swashbuckle seems to generate the correct documentation.

All 20 comments

Can you post the generated swagger spec?

here is the config:

{
  "runtime": "NetCore21",
  "defaultVariables": null,
  "swaggerGenerator": {
    "webApiToSwagger": {
      "controllerNames": [
        "AllInOne.Api.Controllers.Identity.AccountController",
        "AllInOne.Api.Controllers.Identity.AuthenticationController",
        "AllInOne.Api.Controllers.Identity.RoleController",
        "AllInOne.Api.Controllers.Identity.UserController",
        "AllInOne.Api.Controllers.Notifications.NotificationController",
        "AllInOne.Api.Controllers.Samples.SampleController",
        "AllInOne.Api.Controllers.ValuesController"
      ],
      "isAspNetCore": true,
      "resolveJsonOptions": false,
      "defaultUrlTemplate": "api/{controller}/{id?}",
      "addMissingPathParameters": false,
      "includedVersions": null,
      "defaultPropertyNameHandling": "CamelCase",
      "defaultReferenceTypeNullHandling": "Null",
      "defaultEnumHandling": "Integer",
      "flattenInheritanceHierarchy": true,
      "generateKnownTypes": true,
      "generateXmlObjects": false,
      "generateAbstractProperties": false,
      "ignoreObsoleteProperties": false,
      "allowReferencesWithProperties": false,
      "excludedTypeNames": [],
      "serviceHost": null,
      "serviceBasePath": null,
      "serviceSchemes": [],
      "infoTitle": "My Title",
      "infoDescription": null,
      "infoVersion": "1.0.0",
      "documentTemplate": null,
      "documentProcessorTypes": [],
      "operationProcessorTypes": [],
      "typeNameGeneratorType": null,
      "schemaNameGeneratorType": null,
      "contractResolverType": null,
      "serializerSettingsType": null,
      "useDocumentProvider": false,
      "documentName": "v1",
      "aspNetCoreEnvironment": null,
      "createWebHostBuilderMethod": null,
      "startupType": null,
      "allowNullableBodyParameters": true,
      "output": null,
      "outputType": "Swagger2",
      "assemblyPaths": [
        "src/server/AllInOne.Api/bin/Debug/netcoreapp2.1/AllInOne.Api.dll"
      ],
      "assemblyConfig": null,
      "referencePaths": [
        "C:/Program Files/dotnet/shared/Microsoft.NETCore.App/2.1.6",
        "src/server/AllInOne.Api/bin/Debug/netcoreapp2.1/publish",
        "src/server/AllInOne.Api/bin/Debug/netcoreapp2.1/References"
      ],
      "useNuGetCache": true
    }
  },
  "codeGenerators": {
    "swaggerToTypeScriptClient": {
      "className": "{controller}Service",
      "moduleName": "",
      "namespace": "",
      "typeScriptVersion": 2.7,
      "template": "Angular",
      "promiseType": "Promise",
      "httpClass": "HttpClient",
      "useSingletonProvider": false,
      "injectionTokenType": "InjectionToken",
      "rxJsVersion": 6.0,
      "dateTimeType": "Date",
      "nullValue": "Undefined",
      "generateClientClasses": true,
      "generateClientInterfaces": false,
      "generateOptionalParameters": false,
      "exportTypes": true,
      "wrapDtoExceptions": false,
      "clientBaseClass": "ServiceBase",
      "wrapResponses": false,
      "wrapResponseMethods": [],
      "generateResponseClasses": true,
      "responseClass": "SwaggerResponse",
      "protectedMethods": [],
      "configurationClass": null,
      "useTransformOptionsMethod": false,
      "useTransformResultMethod": true,
      "generateDtoTypes": true,
      "operationGenerationMode": "MultipleClientsFromOperationId",
      "markOptionalProperties": true,
      "generateCloneMethod": false,
      "typeStyle": "Class",
      "classTypes": [],
      "extendedClasses": [],
      "extensionCode": "src/client/src/app/services/api.services.extension.ts",
      "generateDefaultValues": true,
      "excludedTypeNames": [],
      "handleReferences": false,
      "generateConstructorInterface": true,
      "convertConstructorInterfaceData": false,
      "importRequiredTypes": true,
      "useGetBaseUrlMethod": false,
      "baseUrlTokenName": "API_BASE_URL",
      "queryNullValue": "",
      "templateDirectory": null,
      "typeNameGeneratorType": null,
      "propertyNameGeneratorType": null,
      "enumNameGeneratorType": null,
      "serviceHost": null,
      "serviceSchemes": null,
      "output": "src/client/src/app/services/api.services.ts"
    }
  }
}

Was it what you want?

As I can't use :

[JsonConverter(typeof(JsonInheritanceConverter))]
[KnownType(typeof(ItemDto))]
[KnownType(typeof(ItemDto))]
[KnownType(typeof(ItemDto))]
[JsonSchemaFlatten]

on an interface, I replaced it to abstract class. Moreover, I realized that I dont need IITemDto in GroupedResultDto. So here is the new code:

    public class GroupedResultDto<TEntity> : GroupedResultDto<TEntity, Guid>
        where TEntity : IEntityDto
    {
    }

    public class GroupedResultDto<TEntity, TPrimaryKey>
        where TEntity : IEntityDto<TPrimaryKey>
    {
        public int TotalCount { get; set; }
        public IEnumerable<GroupItemDto<TEntity, TPrimaryKey>> GroupItems { get; set; }
        public bool HasNext { get; set; }
    }

    public class GroupItemDto<TEntity> : GroupItemDto<TEntity, Guid>
        where TEntity : IEntityDto
    {
    }

    public class GroupItemDto<TEntity, TPrimaryKey>
        where TEntity : IEntityDto<TPrimaryKey>
    {
        public AbstractItemDto Item { get; set; }
        public IEnumerable<TEntity> Items { get; set; }
    }

    [JsonConverter(typeof(JsonInheritanceConverter))]
    [KnownType(typeof(ItemDto<string>))]
    [KnownType(typeof(ItemDto<UserDto>))]
    [KnownType(typeof(ItemDto<NotificationDto>))]
    [JsonSchemaFlatten]
    public abstract class AbstractItemDto
    {
        public abstract string Discriminator { get; }
    }

    public class ItemDto<T> : AbstractItemDto
        where T : IComparable
    {
        public T Key { get; set; }
        public override string Discriminator
        {
            get
            {
                return typeof(T).Name;
            }
        }

        public int CompareTo(object obj)
        {
            if (!(obj is ItemDto<T> item))
            {
                throw new InvalidCastException($"Not able to cast as '{typeof(T).Name}'.");
            }
            return Key.CompareTo(item.Key);
        }
    }

NswagStudio generates ItemDtoOfString, ItemDtoOfUserDto, ItemDtoOfNotificationDto, so I means that the option "Generates schemas for types in KnownTypeAttribute attributes" works correctly. But compared to your wiki (https://github.com/RSuter/NJsonSchema/wiki/Inheritance), I can see that ItemDtoOfString (and others) doesnt extends AbstractItemDto like you have with "export class Dog extends Animal "
here is the code generated by nswag.

export class ItemDtoOfString implements IItemDtoOfString {
    key?: string | undefined;
    discriminator?: string | undefined;

    constructor(data?: IItemDtoOfString) {
        if (data) {
            for (var property in data) {
                if (data.hasOwnProperty(property))
                    (<any>this)[property] = (<any>data)[property];
            }
        }
    }

    init(data?: any) {
        if (data) {
            this.key = data["key"];
            this.discriminator = data["discriminator"];
        }
    }

    static fromJS(data: any): ItemDtoOfString {
        data = typeof data === 'object' ? data : {};
        let result = new ItemDtoOfString();
        result.init(data);
        return result;
    }

    toJSON(data?: any) {
        data = typeof data === 'object' ? data : {};
        data["key"] = this.key;
        data["discriminator"] = this.discriminator;
        return data; 
    }
}

export interface IItemDtoOfString {
    key?: string | undefined;
    discriminator?: string | undefined;
}

export class ItemDtoOfUserDto implements IItemDtoOfUserDto {
    key?: UserDto | undefined;
    discriminator?: string | undefined;

    constructor(data?: IItemDtoOfUserDto) {
        if (data) {
            for (var property in data) {
                if (data.hasOwnProperty(property))
                    (<any>this)[property] = (<any>data)[property];
            }
        }
    }

    init(data?: any) {
        if (data) {
            this.key = data["key"] ? UserDto.fromJS(data["key"]) : <any>undefined;
            this.discriminator = data["discriminator"];
        }
    }

    static fromJS(data: any): ItemDtoOfUserDto {
        data = typeof data === 'object' ? data : {};
        let result = new ItemDtoOfUserDto();
        result.init(data);
        return result;
    }

    toJSON(data?: any) {
        data = typeof data === 'object' ? data : {};
        data["key"] = this.key ? this.key.toJSON() : <any>undefined;
        data["discriminator"] = this.discriminator;
        return data; 
    }
}

export interface IItemDtoOfUserDto {
    key?: UserDto | undefined;
    discriminator?: string | undefined;
}

export class ItemDtoOfNotificationDto implements IItemDtoOfNotificationDto {
    key?: NotificationDto | undefined;
    discriminator?: string | undefined;

    constructor(data?: IItemDtoOfNotificationDto) {
        if (data) {
            for (var property in data) {
                if (data.hasOwnProperty(property))
                    (<any>this)[property] = (<any>data)[property];
            }
        }
    }

    init(data?: any) {
        if (data) {
            this.key = data["key"] ? NotificationDto.fromJS(data["key"]) : <any>undefined;
            this.discriminator = data["discriminator"];
        }
    }

    static fromJS(data: any): ItemDtoOfNotificationDto {
        data = typeof data === 'object' ? data : {};
        let result = new ItemDtoOfNotificationDto();
        result.init(data);
        return result;
    }

    toJSON(data?: any) {
        data = typeof data === 'object' ? data : {};
        data["key"] = this.key ? this.key.toJSON() : <any>undefined;
        data["discriminator"] = this.discriminator;
        return data; 
    }
}

export interface IItemDtoOfNotificationDto {
    key?: NotificationDto | undefined;
    discriminator?: string | undefined;
}

And AbstratItemDto:

export abstract class AbstractItemDto implements IAbstractItemDto {

    constructor(data?: IAbstractItemDto) {
        if (data) {
            for (var property in data) {
                if (data.hasOwnProperty(property))
                    (<any>this)[property] = (<any>data)[property];
            }
        }
    }

    init(data?: any) {
        if (data) {
        }
    }

    static fromJS(data: any): AbstractItemDto {
        data = typeof data === 'object' ? data : {};
        throw new Error("The abstract class 'AbstractItemDto' cannot be instantiated.");
    }

    toJSON(data?: any) {
        data = typeof data === 'object' ? data : {};
        return data; 
    }
}

export interface IAbstractItemDto {
}

I continue to test and try to make it works, If you have any suggestions, please let me know :)

And Maybe you were looking for this:

{
  "x-generator": "NSwag v12.0.0.0 (NJsonSchema v9.12.2.0 (Newtonsoft.Json v11.0.0.0))",
  "swagger": "2.0",
  "info": {
    "title": "My Title",
    "version": "1.0.0"
  },
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "paths": {
    "/api/v1/Account/changepassword": {
      "put": {
        "tags": [
          "Account"
        ],
        "operationId": "Account_ChangePasword",
        "parameters": [
          {
            "name": "dto",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ChangePasswordDto"
            },
            "x-nullable": true
          }
        ],
        "responses": {
          "200": {
            "description": ""
          },
          "401": {
            "description": ""
          },
          "404": {
            "description": ""
          },
          "500": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/ApiErrorDto"
            }
          }
        }
      }
    },
    "/api/v1/Account/updateprofile": {
      "put": {
        "tags": [
          "Account"
        ],
        "operationId": "Account_UpdateProfile",
        "parameters": [
          {
            "name": "dto",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ProfileDto"
            },
            "x-nullable": true
          }
        ],
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/ProfileDto"
            }
          },
          "401": {
            "description": ""
          },
          "404": {
            "description": ""
          },
          "500": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/ApiErrorDto"
            }
          }
        }
      }
    },
    "/api/v1/Authentication/register": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "operationId": "Authentication_Register",
        "parameters": [
          {
            "name": "dto",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/RegistrationDto"
            },
            "x-nullable": true
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/api/v1/Authentication/passwordreset": {
      "put": {
        "tags": [
          "Authentication"
        ],
        "operationId": "Authentication_PasswordReset",
        "parameters": [
          {
            "name": "dto",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/PasswordResetDto"
            },
            "x-nullable": true
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/api/v1/Authentication/login": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "operationId": "Authentication_Login",
        "parameters": [
          {
            "name": "dto",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/CredentialsDto"
            },
            "x-nullable": true
          }
        ],
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "type": "string"
            }
          }
        }
      }
    },
    "/api/Role": {
      "get": {
        "tags": [
          "Role"
        ],
        "operationId": "Role_GetAll",
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/RoleDto"
              }
            }
          },
          "500": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/ApiErrorDto"
            }
          }
        }
      }
    },
    "/api/v1/User/{id}": {
      "get": {
        "tags": [
          "User"
        ],
        "operationId": "User_GetById",
        "parameters": [
          {
            "type": "string",
            "name": "id",
            "in": "path",
            "required": true,
            "format": "guid",
            "x-nullable": false
          }
        ],
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/UserDto"
            }
          },
          "404": {
            "description": ""
          },
          "500": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/ApiErrorDto"
            }
          }
        }
      },
      "delete": {
        "tags": [
          "User"
        ],
        "operationId": "User_Delete",
        "parameters": [
          {
            "type": "string",
            "name": "id",
            "in": "path",
            "required": true,
            "format": "guid",
            "x-nullable": false
          }
        ],
        "responses": {
          "200": {
            "description": ""
          },
          "401": {
            "description": ""
          },
          "404": {
            "description": ""
          },
          "500": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/ApiErrorDto"
            }
          }
        }
      }
    },
    "/api/v1/User": {
      "get": {
        "tags": [
          "User"
        ],
        "operationId": "User_GetAll",
        "parameters": [
          {
            "type": "string",
            "name": "sorting",
            "in": "query",
            "x-schema": {
              "$ref": "#/definitions/UserSortingDto"
            },
            "x-nullable": false,
            "enum": [
              "FullName",
              "Lastname",
              "Email",
              "RoleName"
            ]
          },
          {
            "type": "boolean",
            "name": "ascending",
            "in": "query",
            "x-nullable": false
          },
          {
            "type": "string",
            "name": "filter",
            "in": "query",
            "x-nullable": true
          },
          {
            "type": "integer",
            "name": "maxResultCount",
            "in": "query",
            "format": "int32",
            "x-nullable": true
          },
          {
            "type": "integer",
            "name": "skipCount",
            "in": "query",
            "format": "int32",
            "x-nullable": true
          }
        ],
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/PagedResultDtoOfUserDtoAndNullableOfGuid"
            }
          }
        }
      },
      "post": {
        "tags": [
          "User"
        ],
        "operationId": "User_Create",
        "parameters": [
          {
            "name": "dto",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/NewUserDto"
            },
            "x-nullable": true
          }
        ],
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/UserDto"
            }
          },
          "404": {
            "description": ""
          },
          "500": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/ApiErrorDto"
            }
          }
        }
      }
    },
    "/api/v1/User/{id}/lock": {
      "put": {
        "tags": [
          "User"
        ],
        "operationId": "User_Lock",
        "parameters": [
          {
            "type": "string",
            "name": "id",
            "in": "path",
            "required": true,
            "format": "guid",
            "x-nullable": false
          }
        ],
        "responses": {
          "200": {
            "description": ""
          },
          "401": {
            "description": ""
          },
          "404": {
            "description": ""
          },
          "500": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/ApiErrorDto"
            }
          }
        }
      }
    },
    "/api/v1/User/{id}/unlock": {
      "put": {
        "tags": [
          "User"
        ],
        "operationId": "User_Unlock",
        "parameters": [
          {
            "type": "string",
            "name": "id",
            "in": "path",
            "required": true,
            "format": "guid",
            "x-nullable": false
          }
        ],
        "responses": {
          "200": {
            "description": ""
          },
          "401": {
            "description": ""
          },
          "404": {
            "description": ""
          },
          "500": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/ApiErrorDto"
            }
          }
        }
      }
    },
    "/api/v1/User/roles": {
      "get": {
        "tags": [
          "User"
        ],
        "operationId": "User_GetRoles",
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/RoleDto"
              }
            }
          },
          "500": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/ApiErrorDto"
            }
          }
        }
      }
    },
    "/api/v1/Notification": {
      "get": {
        "tags": [
          "Notification"
        ],
        "operationId": "Notification_GetAll",
        "parameters": [
          {
            "type": "boolean",
            "name": "ascending",
            "in": "query",
            "x-nullable": false
          },
          {
            "type": "integer",
            "name": "grouping",
            "in": "query",
            "x-schema": {
              "$ref": "#/definitions/NotificationGrouping"
            },
            "x-nullable": true,
            "enum": [
              1,
              2,
              3,
              4
            ]
          },
          {
            "type": "boolean",
            "name": "onlyUnread",
            "in": "query",
            "x-nullable": true
          },
          {
            "type": "string",
            "name": "sorting",
            "in": "query",
            "x-schema": {
              "$ref": "#/definitions/NotificationSorting"
            },
            "x-nullable": true,
            "enum": [
              "SortByAction",
              "SortByCreatedAt"
            ]
          },
          {
            "type": "string",
            "name": "filter",
            "in": "query",
            "x-nullable": true
          },
          {
            "type": "integer",
            "name": "maxResultCount",
            "in": "query",
            "format": "int32",
            "x-nullable": true
          },
          {
            "type": "integer",
            "name": "skipCount",
            "in": "query",
            "format": "int32",
            "x-nullable": true
          }
        ],
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/GroupedResultDtoOfNotificationDto"
            }
          },
          "500": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/ApiErrorDto"
            }
          }
        }
      },
      "put": {
        "tags": [
          "Notification"
        ],
        "operationId": "Notification_Read",
        "responses": {
          "200": {
            "description": ""
          },
          "500": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/ApiErrorDto"
            }
          }
        }
      }
    },
    "/api/v1/Sample/{id}": {
      "get": {
        "tags": [
          "Sample"
        ],
        "operationId": "Sample_GetById",
        "parameters": [
          {
            "type": "string",
            "name": "id",
            "in": "path",
            "required": true,
            "format": "guid",
            "x-nullable": false
          }
        ],
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/SampleDetailsDto"
            }
          },
          "404": {
            "description": ""
          },
          "500": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/ApiErrorDto"
            }
          }
        }
      },
      "put": {
        "tags": [
          "Sample"
        ],
        "operationId": "Sample_Update",
        "parameters": [
          {
            "type": "string",
            "name": "id",
            "in": "path",
            "required": true,
            "format": "guid",
            "x-nullable": false
          },
          {
            "name": "dto",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/SampleDetailsDto"
            },
            "x-nullable": true
          }
        ],
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/SampleDetailsDto"
            }
          },
          "404": {
            "description": ""
          },
          "500": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/ApiErrorDto"
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Sample"
        ],
        "operationId": "Sample_Delete",
        "parameters": [
          {
            "type": "string",
            "name": "id",
            "in": "path",
            "required": true,
            "format": "guid",
            "x-nullable": false
          }
        ],
        "responses": {
          "200": {
            "description": ""
          },
          "404": {
            "description": ""
          },
          "500": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/ApiErrorDto"
            }
          }
        }
      }
    },
    "/api/v1/Sample": {
      "get": {
        "tags": [
          "Sample"
        ],
        "operationId": "Sample_GetAll",
        "parameters": [
          {
            "type": "string",
            "name": "sorting",
            "in": "query",
            "x-schema": {
              "$ref": "#/definitions/SampleSorting"
            },
            "x-nullable": true,
            "enum": [
              "Text",
              "TextDescending",
              "CreatedAt",
              "CreatedAtDescending",
              "CreatedBy",
              "CreatedByDescending",
              "UpdatedAt",
              "UpdatedAtDescending",
              "UpdatedBy",
              "UpdatedByDescending"
            ]
          },
          {
            "type": "boolean",
            "name": "ascending",
            "in": "query",
            "x-nullable": false
          },
          {
            "type": "string",
            "name": "filter",
            "in": "query",
            "x-nullable": true
          },
          {
            "type": "integer",
            "name": "maxResultCount",
            "in": "query",
            "format": "int32",
            "x-nullable": true
          },
          {
            "type": "integer",
            "name": "skipCount",
            "in": "query",
            "format": "int32",
            "x-nullable": true
          }
        ],
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/PagedResultDtoOfSampleDtoAndNullableOfGuid"
            }
          },
          "500": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/ApiErrorDto"
            }
          }
        }
      },
      "post": {
        "tags": [
          "Sample"
        ],
        "operationId": "Sample_Create",
        "parameters": [
          {
            "name": "dto",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/SampleDetailsDto"
            },
            "x-nullable": true
          }
        ],
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/SampleDetailsDto"
            }
          },
          "500": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/ApiErrorDto"
            }
          }
        }
      }
    },
    "/api/v1/Sample/SayHello": {
      "get": {
        "tags": [
          "Sample"
        ],
        "operationId": "Sample_SayHello",
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/SampleDto"
            }
          }
        }
      }
    },
    "/api/v1/Sample/SayHelloUser": {
      "get": {
        "tags": [
          "Sample"
        ],
        "operationId": "Sample_SayHelloUser",
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/SampleDto"
            }
          }
        }
      }
    },
    "/api/v1/Sample/SayHelloAdmistrator": {
      "get": {
        "tags": [
          "Sample"
        ],
        "operationId": "Sample_SayHelloAdmistrator",
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/SampleDto"
            }
          }
        }
      }
    },
    "/api/v1/Sample/SayHelloManager": {
      "get": {
        "tags": [
          "Sample"
        ],
        "operationId": "Sample_SayHelloManager",
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/SampleDto"
            }
          }
        }
      }
    },
    "/api/v1/Sample/SendEmail": {
      "get": {
        "tags": [
          "Sample"
        ],
        "operationId": "Sample_SendEmail",
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "$ref": "#/definitions/SampleDto"
            }
          }
        }
      }
    },
    "/api/v1/Values": {
      "get": {
        "tags": [
          "Values"
        ],
        "operationId": "Values_GetAll",
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Values"
        ],
        "operationId": "Values_Post",
        "parameters": [
          {
            "name": "value",
            "in": "body",
            "required": true,
            "schema": {
              "type": "string"
            },
            "x-nullable": true
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/api/v1/Values/{id}": {
      "get": {
        "tags": [
          "Values"
        ],
        "operationId": "Values_Get",
        "parameters": [
          {
            "type": "integer",
            "name": "id",
            "in": "path",
            "required": true,
            "format": "int32",
            "x-nullable": false
          }
        ],
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "put": {
        "tags": [
          "Values"
        ],
        "operationId": "Values_Put",
        "parameters": [
          {
            "type": "integer",
            "name": "id",
            "in": "path",
            "required": true,
            "format": "int32",
            "x-nullable": false
          },
          {
            "name": "value",
            "in": "body",
            "required": true,
            "schema": {
              "type": "string"
            },
            "x-nullable": true
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      },
      "delete": {
        "tags": [
          "Values"
        ],
        "operationId": "Values_Delete",
        "parameters": [
          {
            "type": "integer",
            "name": "id",
            "in": "path",
            "required": true,
            "format": "int32",
            "x-nullable": false
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/api/v1/Configuration/settings": {
      "get": {
        "tags": [
          "Configuration"
        ],
        "operationId": "Configuration_GetSettings",
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/ValueTupleOfStringAndString"
              }
            }
          }
        }
      }
    },
    "/api/v1/Configuration/environment": {
      "get": {
        "tags": [
          "Configuration"
        ],
        "operationId": "Configuration_GetEnv",
        "responses": {
          "200": {
            "x-nullable": true,
            "description": "",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/ValueTupleOfStringAndString"
              }
            }
          }
        }
      }
    }
  },
  "definitions": {
    "ApiErrorDto": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "isError"
      ],
      "properties": {
        "message": {
          "type": "string"
        },
        "isError": {
          "type": "boolean"
        },
        "details": {
          "type": "string"
        }
      }
    },
    "ChangePasswordDto": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "currentPassword",
        "newPassword",
        "newPasswordConfirmation"
      ],
      "properties": {
        "currentPassword": {
          "type": "string",
          "minLength": 1
        },
        "newPassword": {
          "type": "string",
          "minLength": 1
        },
        "newPasswordConfirmation": {
          "type": "string",
          "minLength": 1
        }
      }
    },
    "ProfileDto": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "firstName": {
          "type": "string"
        },
        "lastName": {
          "type": "string"
        }
      }
    },
    "RegistrationDto": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "email",
        "password",
        "passwordConfirmation",
        "firstname",
        "lastname"
      ],
      "properties": {
        "email": {
          "type": "string",
          "minLength": 1
        },
        "password": {
          "type": "string",
          "minLength": 1
        },
        "passwordConfirmation": {
          "type": "string",
          "minLength": 1
        },
        "firstname": {
          "type": "string",
          "minLength": 1
        },
        "lastname": {
          "type": "string",
          "minLength": 1
        }
      }
    },
    "PasswordResetDto": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "email": {
          "type": "string"
        }
      }
    },
    "CredentialsDto": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "email",
        "password"
      ],
      "properties": {
        "email": {
          "type": "string",
          "minLength": 1
        },
        "password": {
          "type": "string",
          "minLength": 1
        }
      }
    },
    "RoleDto": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id"
      ],
      "properties": {
        "id": {
          "type": "string",
          "format": "guid"
        },
        "name": {
          "type": "string"
        }
      }
    },
    "UserDto": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "isLocked"
      ],
      "properties": {
        "id": {
          "type": "string",
          "format": "guid"
        },
        "firstname": {
          "type": "string"
        },
        "lastname": {
          "type": "string"
        },
        "fullName": {
          "type": "string"
        },
        "email": {
          "type": "string"
        },
        "isLocked": {
          "type": "boolean"
        },
        "roleName": {
          "type": "string"
        },
        "createdBy": {
          "type": "string"
        },
        "updatedBy": {
          "type": "string"
        },
        "deletedBy": {
          "type": "string"
        },
        "createdAt": {
          "type": "string"
        },
        "updatedAt": {
          "type": "string"
        },
        "deletedAt": {
          "type": "string"
        }
      }
    },
    "PagedResultDtoOfUserDtoAndNullableOfGuid": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "totalCount",
        "hasNext"
      ],
      "properties": {
        "totalCount": {
          "type": "integer",
          "format": "int32"
        },
        "items": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/UserDto"
          }
        },
        "hasNext": {
          "type": "boolean"
        }
      }
    },
    "UserSortingDto": {
      "type": "string",
      "description": "",
      "x-enumNames": [
        "FullName",
        "Lastname",
        "Email",
        "RoleName"
      ],
      "enum": [
        "FullName",
        "Lastname",
        "Email",
        "RoleName"
      ]
    },
    "NewUserDto": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "email",
        "password",
        "passwordConfirmation",
        "firstname",
        "lastname",
        "roleId"
      ],
      "properties": {
        "email": {
          "type": "string",
          "minLength": 1
        },
        "password": {
          "type": "string",
          "minLength": 1
        },
        "passwordConfirmation": {
          "type": "string",
          "minLength": 1
        },
        "firstname": {
          "type": "string",
          "minLength": 1
        },
        "lastname": {
          "type": "string",
          "minLength": 1
        },
        "roleId": {
          "type": "string",
          "format": "guid"
        }
      }
    },
    "GroupedResultDtoOfNotificationDto": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "totalCount",
        "hasNext"
      ],
      "properties": {
        "totalCount": {
          "type": "integer",
          "format": "int32"
        },
        "groupItems": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/GroupItemDtoOfNotificationDtoAndGuid"
          }
        },
        "hasNext": {
          "type": "boolean"
        }
      }
    },
    "GroupItemDtoOfNotificationDtoAndGuid": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "item": {
          "$ref": "#/definitions/AbstractItemDto"
        },
        "items": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/NotificationDto"
          }
        }
      }
    },
    "AbstractItemDto": {
      "type": "object",
      "x-abstract": true,
      "additionalProperties": false
    },
    "ItemDtoOfString": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "key": {
          "type": "string"
        },
        "discriminator": {
          "type": "string"
        }
      }
    },
    "ItemDtoOfUserDto": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "key": {
          "$ref": "#/definitions/UserDto"
        },
        "discriminator": {
          "type": "string"
        }
      }
    },
    "ItemDtoOfNotificationDto": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "key": {
          "$ref": "#/definitions/NotificationDto"
        },
        "discriminator": {
          "type": "string"
        }
      }
    },
    "NotificationDto": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id"
      ],
      "properties": {
        "id": {
          "type": "string",
          "format": "guid"
        },
        "action": {
          "type": "string"
        },
        "label": {
          "type": "string"
        },
        "entity": {},
        "discriminator": {
          "type": "string"
        },
        "createdBy": {
          "type": "string"
        },
        "createdAt": {
          "type": "string"
        }
      }
    },
    "NotificationGrouping": {
      "type": "integer",
      "description": "",
      "x-enumNames": [
        "GroupByCreatedAt",
        "GroupByCreatedByUser",
        "GroupByEntity",
        "GroupByAction"
      ],
      "enum": [
        1,
        2,
        3,
        4
      ]
    },
    "NotificationSorting": {
      "type": "string",
      "description": "",
      "x-enumNames": [
        "SortByAction",
        "SortByCreatedAt"
      ],
      "enum": [
        "SortByAction",
        "SortByCreatedAt"
      ]
    },
    "SampleDetailsDto": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "text"
      ],
      "properties": {
        "text": {
          "type": "string",
          "minLength": 1
        },
        "image": {
          "$ref": "#/definitions/EncodedFileDto"
        },
        "createdBy": {
          "type": "string"
        },
        "updatedBy": {
          "type": "string"
        },
        "deletedBy": {
          "type": "string"
        },
        "createdAt": {
          "type": "string"
        },
        "updatedAt": {
          "type": "string"
        },
        "deletedAt": {
          "type": "string"
        },
        "id": {
          "type": "string",
          "format": "guid"
        },
        "sampleItems": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/SampleItemDto"
          }
        }
      }
    },
    "EncodedFileDto": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "name",
        "contentType",
        "contentLength",
        "content"
      ],
      "properties": {
        "url": {
          "type": "string"
        },
        "name": {
          "type": "string",
          "minLength": 1
        },
        "contentType": {
          "type": "string",
          "minLength": 1
        },
        "contentLength": {
          "type": "integer",
          "format": "int32"
        },
        "content": {
          "type": "string",
          "minLength": 1
        }
      }
    },
    "SampleItemDto": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "text"
      ],
      "properties": {
        "id": {
          "type": "string",
          "format": "guid"
        },
        "text": {
          "type": "string",
          "minLength": 1
        },
        "createdBy": {
          "type": "string"
        },
        "updatedBy": {
          "type": "string"
        },
        "deletedBy": {
          "type": "string"
        },
        "createdAt": {
          "type": "string"
        },
        "updatedAt": {
          "type": "string"
        },
        "deletedAt": {
          "type": "string"
        }
      }
    },
    "PagedResultDtoOfSampleDtoAndNullableOfGuid": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "totalCount",
        "hasNext"
      ],
      "properties": {
        "totalCount": {
          "type": "integer",
          "format": "int32"
        },
        "items": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/SampleDto"
          }
        },
        "hasNext": {
          "type": "boolean"
        }
      }
    },
    "SampleDto": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "text"
      ],
      "properties": {
        "id": {
          "type": "string",
          "format": "guid"
        },
        "text": {
          "type": "string",
          "minLength": 1
        },
        "image": {
          "$ref": "#/definitions/EncodedFileDto"
        },
        "createdBy": {
          "type": "string"
        },
        "updatedBy": {
          "type": "string"
        },
        "deletedBy": {
          "type": "string"
        },
        "createdAt": {
          "type": "string"
        },
        "updatedAt": {
          "type": "string"
        },
        "deletedAt": {
          "type": "string"
        }
      }
    },
    "SampleSorting": {
      "type": "string",
      "description": "",
      "x-enumNames": [
        "Text",
        "TextDescending",
        "CreatedAt",
        "CreatedAtDescending",
        "CreatedBy",
        "CreatedByDescending",
        "UpdatedAt",
        "UpdatedAtDescending",
        "UpdatedBy",
        "UpdatedByDescending"
      ],
      "enum": [
        "Text",
        "TextDescending",
        "CreatedAt",
        "CreatedAtDescending",
        "CreatedBy",
        "CreatedByDescending",
        "UpdatedAt",
        "UpdatedAtDescending",
        "UpdatedBy",
        "UpdatedByDescending"
      ]
    },
    "ValueTupleOfStringAndString": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "item1": {
          "type": "string"
        },
        "item2": {
          "type": "string"
        }
      }
    }
  }
}

Hi @RSuter did you find a way to help me? Did you think to different solution?
Maybe it can help me to think to a solution too?
Let me know :)

The solution is (the _fromJS_ part):

export abstract class AbstractItemDto implements IAbstractItemDto {

  constructor(data?: IAbstractItemDto) {
    debugger;
    if (data) {
      for (var property in data) {
        if (data.hasOwnProperty(property))
          (<any>this)[property] = (<any>data)[property];
      }
    }
  }

  init(data?: any) {
    if (data) {
    }
  }

  static fromJS(data: any): AbstractItemDto {
    data = typeof data === 'object' ? data : {};
    if (data.discriminator == "NotificationDto") {
      return ItemDtoOfNotificationDto.fromJS(data);
    }
    if (data.discriminator == "UserDto") {
      return ItemDtoOfUserDto.fromJS(data);
    }
    if (data.discriminator == "string") {
      return ItemDtoOfString.fromJS(data);
    }
    throw new Error("The abstract class 'AbstractItemDto' cannot be instantiated.");
  }

  toJSON(data?: any) {
    data = typeof data === 'object' ? data : {};
    return data;
  }
}

I dont know how your code works, but what I could imagine is during the generation of Typescripts services, when there is an abstract class, the generation tool must take the _KnowTypeAttribute_ to generate the _FromJs_ part.

Example:

    [JsonConverter(typeof(JsonInheritanceConverter))]
    [KnownType(typeof(ItemDto<string>))]
    [KnownType(typeof(ItemDto<UserDto>))]
    [KnownType(typeof(ItemDto<NotificationDto>))]
    [JsonSchemaFlatten]
    public abstract class AbstractItemDto
    {
        public abstract string Discriminator { get; }
    }

Maybe it s too custom? Let me know, I will try to adapt my code to your solution.

To continue to work untill a fix will be found (crossing the fingers), I choose a workaround to avoid the generation of AbstractItemDto, I added it here in Nswagstudio:
image

but GroupItemDtoOfNotificationDtoAndGuid need as AbstractItemDto is the type of one of his property .

I will continue to investigate :)

Any help will be welcome

So much information in one issue… :-)

Can you provide a simple sample app where all this can be reproduced?

I'd say that json inheritance and schema flatten attributes are mutually exclusive - but I personally didnt have this scenario, so it's very hard to say how the system reacts...

I wanted to be exhaustive, sorry maybe I was too much :).

I created a repository to reproduce the issue: https://github.com/ranouf/TestNotification

You just need to launch the app, open the console in the browser, you will see this error:

core.js:14597 ERROR Error: The abstract class 'AbstractItemDto' cannot be instantiated.
at Function.push../src/app/services/api.services.ts.AbstractItemDto.fromJS (api.services.ts:227)
at GroupItemDtoOfNotificationDtoAndGuid.push../src/app/services/api.services.ts.GroupItemDtoOfNotificationDtoAndGuid.init (api.services.ts:176)
at Function.push../src/app/services/api.services.ts.GroupItemDtoOfNotificationDtoAndGuid.fromJS (api.services.ts:188)
at GroupedResultDtoOfNotificationDto.push../src/app/services/api.services.ts.GroupedResultDtoOfNotificationDtoAndGuid.init (api.services.ts:100)
at GroupedResultDtoOfNotificationDto.push../src/app/services/api.services.ts.GroupedResultDtoOfNotificationDto.init (api.services.ts:139)
at Function.push../src/app/services/api.services.ts.GroupedResultDtoOfNotificationDto.fromJS (api.services.ts:147)
at MergeMapSubscriber.project (api.services.ts:68)
at MergeMapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapSubscriber._tryNext (mergeMap.js:61)
at MergeMapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapSubscriber._next (mergeMap.js:51)
at MergeMapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next (Subscriber.js:54)

What I would like:

  • Solution 1: nswag studio can generate correctly _AbstractItemDto.fromJS_ using the discriminator from _KnownTypeAttribute_ in _AbstractItemDto.cs_ Example:
static fromJS(data: any): AbstractItemDto {
    data = typeof data === 'object' ? data : {};
    if (data.discriminator == "notificationDto") { //or itemDtoOfNotificationDto if you prefer, i will update the cs code file
      return ItemDtoOfNotificationDto.fromJS(data);
    }
    if (data.discriminator == "userDto") {
      return ItemDtoOfUserDto.fromJS(data);
    }
    if (data.discriminator == "string") {
      return ItemDtoOfString.fromJS(data);
    }
    throw new Error("The abstract class 'AbstractItemDto' cannot be instantiated.");
  }
  • Solution 2: nswag studio can allow me to overwrite _AbstractItemDto.fromJS_ (but I prefer the solution 1)

Or another solution if you have other idea.

Thanks for your help @RSuter

@RSuter could you add me the right to publish a new branch to NJsonSchema please?

I created a branch who help to resolve this issue. Currently _JsonInheritanceConverter_ take the Type.Name from Reflection, but there is a generic type, it generate "_ItemDtoOfT`1_" instead of "_ItemDtoOfTUserDto_" as we need in the TypeScriptApi Service. So I created this extension:

    public static class TypeExtensions
    {
        public static string GetGenericName(this Type t)
        {
            if (!t.IsGenericType)
                return t.Name;
            var genericTypeName = t.GetGenericTypeDefinition().Name;
            genericTypeName = genericTypeName.Substring(0, genericTypeName.IndexOf('`'));
            var genericArgs = string.Join(
                ",",
                t.GetGenericArguments().Select(GetGenericName)
            );
            return genericTypeName + "Of" + genericArgs;
        }
    }

source: https://stackoverflow.com/a/2448918/6123422

and updated JsonInheritanceConverter with:

        public virtual string GetDiscriminatorValue(Type type)
        {
            return type.GetGenericName();
        }

currently the branch doesnt compile because of this:
image

I think maybe this could fix it, but not sure, what do you do when you have this error?

#if !NETSTANDARD
            if (!t.IsGenericType)
                return t.Name;
            var genericTypeName = t.GetGenericTypeDefinition().Name;
            genericTypeName = genericTypeName.Substring(0, genericTypeName.IndexOf('`'));
            var genericArgs = string.Join(
                ",",
                t.GetGenericArguments().Select(GetGenericName)
            );
            return genericTypeName + "Of" + genericArgs;
#else
            return t.Name;
#endif

let me know if it s ok for you?

could you add me the right to publish a new branch to NJsonSchema please?

Can you please create a fork and create a PR?

currently the branch doesnt compile because of this:

Each target should have the same feature, so this #if is not really an option (because this would not work on .NET Core then) - but have you tried t.GetTypeInfo().IsGenericType or a similar property?

Thanks, I will try to do that. Will be the first time :)

Any update on this? Is this fixed? (Sorry there are lots of issues :-)

Hi, I m in holiday, I will watch that in January, merry Christmas and happy
new year ;)

Le ven. 21 déc. 2018 16 h 59, Rico Suter notifications@github.com a
écrit :

Any update on this? Is this fixed? (Sorry there are lots of issues :-)

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/RSuter/NSwag/issues/1766#issuecomment-449426132, or mute
the thread
https://github.com/notifications/unsubscribe-auth/ABrspwIuXQOW7aRv3LbnQsQloK0ScJ2zks5u7QVKgaJpZM4Yw5jq
.

Hi @ranouf / @RSuter any updates on this? In a perfect world I would like to use interfaces and not abstract classes as proposed.

Add to this, Swashbuckle seems to generate the correct documentation.

Hi @RicoSuter ,

After I switched from Swashbuckle to NSwag for my Swagger generation, my generated TypeScript also broke with this error.

Simplest way is to just set GenerateAbstractSchemas to false, but we should still try to fix this. Please provide a sample where the TS code tries to instantiate an abstract class

GenerateAbstractSchemas to false doesn't resolve the issue for me.
It still generates IEnumerable for me.

Hello guys,
Any update on this issue ?
I'm working with smart enums and nswag does not take inot consideration child classes.

image

here's the error :

image

i have the same exact problem that had ranouf.

Edit : SOLVED The problem with this solution :
image

Yep, it's more a Newtonsoft serialization problem at runtime (not NSwag/NJS), for more information (your solution), see https://github.com/RicoSuter/NJsonSchema/wiki/Inheritance

I'm still facing this issue

Was this page helpful?
0 / 5 - 0 ratings