Using Swashbuckle ISchemaFilter to set the default description of input parameters
Asked Answered
N

2

5

I want to add default description in schema of documentation for all input parameters with DateTime type. So the clients will understand which formats we are using etc.

Can I create my custom implementation of ISchemaFilter for this purposes?

I know that I can add description by using xml comments, but in this case I should copy and paste the same text in many places where I have filter by date.

I have tried to use MapType for this. But as far as I understand it works only for response types(at least in my case it works only for response models). I found the similar question but it still unanswered

options.MapType<DateTime> (() => new Schema {
  Type = "string",
  Format = "date-time",
  Description = "Description"
});

I also have tried my custom DateTimeSchemaFilter, but no descriptions were added for my input parameters. I have already tried configuration without xml and/or MapType. In debug mode I see that my filter is being called but nothing happened in UI.

public class DateTimeSchemaFilter: ISchemaFilter {

    public void Apply(Schema schema, SchemaFilterContext context) 
    {
        var typeInfo = context.SystemType;
        if (typeInfo == typeof(DateTime ? )) 
        {
            schema.Description = "Description";
        }
    }
}

services.AddSwaggerGen(options => {

    options.DescribeAllEnumsAsStrings();

    var xmlFile = $ {Assembly.GetExecutingAssembly().GetName().Name}.xml";
    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
    options.IncludeXmlComments(xmlPath);

    options.MapType<DateTime> (() => new Schema {
        Type = "string",
        Format = "date-time",
        Description = "Description"
    }); 

    options.SchemaFilter<DateTimeSchemaFilter>();

});

public async Task<IActionResult> GetTelemetries(
        string nodeId, 
        int offset = 0, 
        int limit = DEFAULT_PAGE_LIMIT,
        TelemetryChannel channel = TelemetryChannel.Temperature,
        DateTime? dateFrom = null,
        DateTime? dateTo = null)
    {
        var result = await _telemetryService.GetTelemetries(nodeId, offset, limit);

        return BaseResponse(result);
    }

Here is my Swagger documentation output

Nonentity answered 8/7, 2019 at 13:52 Comment(0)
S
5

If you have custom schema filter...

public class DateTimeSchemaFilter: ISchemaFilter {

    public void Apply(Schema schema, SchemaFilterContext context) 
    {
        var typeInfo = context.SystemType;
        if (typeInfo == typeof(DateTime ? )) 
        {
            schema.Description = "Description";
        }
    }
}

... you can register it using this annotation:

[SwaggerSchemaFilter(typeof(DateTimeSchemaFilter))]
public class YourModel
{
    public int Description { get; set; }
}

Annotations are available as NuGet package: https://www.nuget.org/packages/Swashbuckle.AspNetCore.Annotations

You need to register annotations in swagger generator (Startup.cs):

services.AddSwaggerGen(x =>
{
   x.EnableAnnotations();
});
Stiver answered 8/7, 2019 at 19:56 Comment(1)
I know about annotations but it works only for models as input parameter. So if I move my filters by dates to TelemetriesOptions(for example) class and will use it in API endpoint as input parameter instead of current parameters(dateFro, dateTo) it will work perfect(thanks for pointing that annotations should be enabled in Startup). But I want have all input parameters in query(please check my API endpoint example).In this case, the annotation will not work(it works only with classes). I can add description through xml comments. But I want to find the more elegant way if this is possibleNonentity
B
1

I had the same problem - I'd set up an ISchemaFilter to populate the description (in my case, I was doing it based on the presence of attributes).

I could see my filter was getting called and the description was being set, yet when I looked in SwaggerUI / the OpenAPI spec file, the description was missing.

Turns out it had been clobbered by the code to include XML comments i.e.

                foreach (var assembly in new[] { typeof(SomeType).Assembly, typeof(AnotherType).Assembly })
                {
                    var filePath = Path.Combine(AppContext.BaseDirectory, $"{assembly.GetName().Name}.xml");
                    c.IncludeXmlComments(filePath, true);
                }

When I shifted the schema filter registration to come after XmlComments stuff (which implicitly adds a schema filter) everything worked as I expected.

NB: Take care when updating your description, maybe you want to append to it (if non-null) rather than overwriting it.

Broca answered 27/5, 2020 at 0:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.