Classes Added Using GenerateSchema Appear in the Swagger UI But Not in swagger.json

Geoff Olding 21 Reputation points
2022-07-13T13:59:30.463+00:00

Hello there

I have an Asp.Net Core C# back end project containing controllers and web api methods. Swagger is used to test the web api methods, and to generate swagger.json - we are generating class definitions for the front end to use using nswag studio, based on swagger.json.

I need to add explicitly add some additional class definition to swagger.json. These are for classes which do not appear in any web api endpoints, but which we send to our front end using SignalR.

I have added the additional class definitions using GenerateSchema(). These additional class definitions appear in the Swagger UI (https://localhost:7103/swagger/index.html), but do not appear in swagger.json, for reasons which are unclear. I get the same results when using RegisterType().

Any help on being able to include these definitions in swagger.json would be greatly appreciated.

The code is as follows:

services.AddSwaggerGen(options =>
{
...
options.DocumentFilter<AdditionalSchemasDocumentFilter>();
...
});

public class AdditionalSchemasDocumentFilter : IDocumentFilter
{
...
context.SchemaGenerator.GenerateSchema(typeof(Notification), context.SchemaRepository);
}

app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint($"/swagger/v1/swagger.json", "BackOffice API");
...
});

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,023 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
9,977 questions
0 comments No comments
{count} votes

Accepted answer
  1. Qing Guo - MSFT 881 Reputation points Microsoft Vendor
    2022-07-14T12:16:17.707+00:00

    Hi @Geoff Olding ,

    These additional class definitions appear in the Swagger UI (https://localhost:7103/swagger/index.html), but do not appear in swagger.json,

    Below is a demo, you can refer to it.

    PolymorphismDocumentFilter:

    using Microsoft.OpenApi.Any;  
    using Microsoft.OpenApi.Models;  
    using Swashbuckle.AspNetCore.SwaggerGen;  
    using System;  
    using System.Linq;  
    using System.Reflection;  
      
    namespace swagarcore5  
    {  
        public class PolymorphismDocumentFilter<T> : IDocumentFilter  
        {  
            public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)  
            {  
                RegisterSubClasses(context, typeof(T));  
            }  
      
            private static void RegisterSubClasses(DocumentFilterContext context, Type abstractType)  
            {  
                const string discriminatorName = "$type";  
                var schemaRepository = context.SchemaRepository.Schemas;  
                var schemaGenerator = context.SchemaGenerator;  
      
                if (!schemaRepository.TryGetValue(abstractType.Name, out OpenApiSchema parentSchema))  
                {  
                    parentSchema = schemaGenerator.GenerateSchema(abstractType, context.SchemaRepository);  
                }  
      
                // set up a discriminator property (it must be required)  
                parentSchema.Discriminator = new OpenApiDiscriminator { PropertyName = discriminatorName };  
                parentSchema.Required.Add(discriminatorName);  
      
                if (!parentSchema.Properties.ContainsKey(discriminatorName))  
                    parentSchema.Properties.Add(discriminatorName, new OpenApiSchema { Type = "string", Default = new OpenApiString(abstractType.FullName) });  
      
                // register all subclasses  
                var derivedTypes = abstractType.GetTypeInfo().Assembly.GetTypes()  
                    .Where(x => abstractType != x && abstractType.IsAssignableFrom(x));  
      
                foreach (var type in derivedTypes)  
                    schemaGenerator.GenerateSchema(type, context.SchemaRepository);  
            }  
        }  
    }  
    

    BaseClass:

     public class BaseClass  
        {  
            public string Name { get; set; }      
            public string Description { get; set; }  
        }  
    

    register it in your Startup class

    services.AddSwaggerGen(options =>  
    {  
    ...  
    options.DocumentFilter<PolymorphismDocumentFilter<BaseClass>>();  
    ...  
    });  
    

    result:

    220720-2.png

    ----------

    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,
    Qing Guo

    0 comments No comments

0 additional answers

Sort by: Most helpful