Search code examples
asp.net-core.net-coreswaggerswagger-codegennswag

NSwag generates base class even though JsonSchemaFlattenAttribute is set


I am using NSwag for my ASP.NET Core web api project and just can't get it to work. What I'm trying to do is to exclude some of the base properties of IdentityUser. Here is my custom user class:

[DataContract]
[JsonSchemaFlattenAttribute]
public class User : IdentityUser
{
    // Overridden variables
    [DataMember( Name = "id" )]
    [PersonalData]
    public new string Id { get; set; }

    [DataMember( Name = "email" )]
    [ProtectedPersonalData]
    public new string Email { get; set; }

    [IgnoreDataMember]
    [JsonSchemaIgnoreAttribute]
    public new DateTimeOffset? LockoutEnd { get; set; }

    [PersonalData]
    [IgnoreDataMember]
    [JsonSchemaIgnoreAttribute]
    public new bool TwoFactorEnabled { get; set; }

    [PersonalData]
    [IgnoreDataMember]
    [JsonSchemaIgnoreAttribute]
    public new bool PhoneNumberConfirmed { get; set; }

    [ProtectedPersonalData]
    [IgnoreDataMember]
    [JsonSchemaIgnoreAttribute]
    public new string PhoneNumber { get; set; }

    [IgnoreDataMember]
    [JsonSchemaIgnoreAttribute]
    public new string ConcurrencyStamp { get; set; }

    [IgnoreDataMember]
    [JsonSchemaIgnoreAttribute]
    public new string SecurityStamp { get; set; }

    [IgnoreDataMember]
    [JsonSchemaIgnoreAttribute]
    public new string PasswordHash { get; set; }

    [PersonalData]
    [IgnoreDataMember]
    [JsonSchemaIgnoreAttribute]
    public new bool EmailConfirmed { get; set; }

    [IgnoreDataMember]
    [JsonSchemaIgnoreAttribute]
    public new string NormalizedEmail { get; set; }

    [IgnoreDataMember]
    [JsonSchemaIgnoreAttribute]
    public new string NormalizedUserName { get; set; }

    [ProtectedPersonalData]
    [IgnoreDataMember]
    [JsonSchemaIgnoreAttribute]
    public new string UserName { get; set; }

    [IgnoreDataMember]
    [JsonSchemaIgnoreAttribute]
    public new bool LockoutEnabled { get; set; }

    [IgnoreDataMember]
    [JsonSchemaIgnoreAttribute]
    public new int AccessFailedCount { get; set; }

    // Custom variables
    [DataMember( Name = "date_joined_utc" )]
    public DateTime DateJoinedUtc { get; set; }

    [IgnoreDataMember]
    [JsonSchemaIgnoreAttribute]
    public virtual ICollection<RefreshToken> RefreshTokens { get; set; }

    // Optimistic concurrency
    [Timestamp]
    [IgnoreDataMember]
    [JsonSchemaIgnoreAttribute]
    public byte[] RowVersion { get; set; }
}

Which generates:

"User": {
  "type": "object",
  "required": [
    "dateJoinedUtc"
  ],
  "properties": {
    "id": {
      "type": "string"
    },
    "email": {
      "type": "string"
    },
    "dateJoinedUtc": {
      "type": "string",
      "format": "date-time"
    }
  },
  "allOf": [
    {
      "$ref": "#/definitions/IdentityUserOfString"
    },
    {}
  ]
},
"IdentityUserOfString": {
  "type": "object",
  "required": [
    "emailConfirmed",
    "phoneNumberConfirmed",
    "twoFactorEnabled",
    "lockoutEnabled",
    "accessFailedCount"
  ],
  "properties": {
    "id": {
      "type": "string"
    },
    "userName": {
      "type": "string"
    },
    "normalizedUserName": {
      "type": "string"
    },
    "email": {
      "type": "string"
    },
    "normalizedEmail": {
      "type": "string"
    },
    "emailConfirmed": {
      "type": "boolean"
    },
    "passwordHash": {
      "type": "string"
    },
    "securityStamp": {
      "type": "string"
    },
    "concurrencyStamp": {
      "type": "string"
    },
    "phoneNumber": {
      "type": "string"
    },
    "phoneNumberConfirmed": {
      "type": "boolean"
    },
    "twoFactorEnabled": {
      "type": "boolean"
    },
    "lockoutEnd": {
      "type": "string",
      "format": "date-time"
    },
    "lockoutEnabled": {
      "type": "boolean"
    },
    "accessFailedCount": {
      "type": "integer",
      "format": "int32"
    }
  }
},

My understanding of JsonSchemaFlattenAttribute is that it should exclude the base classes and put every property in the derived class. So why is the class IdentityUserOfString generated? What am I missing?


Solution

  • For some reason setting OpenApiIgnore on the User class solved it:

    [DataContract]
    //[JsonSchemaFlattenAttribute]
    [OpenApiIgnore]
    public class User : IdentityUser
    

    Generates:

    "User": {
      "type": "object",
      "required": [
        "dateJoinedUtc"
      ],
      "properties": {
        "id": {
          "type": "string"
        },
        "email": {
          "type": "string"
        },
        "dateJoinedUtc": {
          "type": "string",
          "format": "date-time"
        }
      }
    },