Home

Awesome

<p align="center"> <a href="https://www.nuget.org/packages/Unchase.Swashbuckle.AspNetCore.Extensions/"> <img src="assets/logo.png" alt="Unchase Swashbuckle Asp.Net Core Extensions Logo"> </a> </p>

Unchase Swashbuckle Asp.Net Core Extensions is a library contains a bunch of extensions (filters) for Swashbuckle.AspNetCore.

The project is developed and maintained by Nikolay Chebotov (Unchase).

Breaking Changes

For old versions see README_OLD.md.

Compatibility

Swashbuckle VersionASP.NET CoreSwagger / OpenAPI Spec.This extension Version
master>= 2.0.02.0, 3.0master
6.1.5>= 2.0.02.0, 3.0v2.6.1
6.1.0>= 2.0.02.0, 3.0v2.6.0
6.0.0>= 2.0.02.0, 3.0v2.5.1
5.0.0>= 2.0.02.0, 3.0v2.0.0
4.0.0>= 2.0.0, < 3.0.02.0v1.1.4

Getting Started

To use the extensions, install NuGet package into your project:

Manually with the NuGet Package Manager:

Install-Package Unchase.Swashbuckle.AspNetCore.Extensions

Using the .NET CLI:

dotnet add package Unchase.Swashbuckle.AspNetCore.Extensions --version {version}

Where {version} is the version of the package you want to install. For example, dotnet add package Unchase.Swashbuckle.AspNetCore.Extensions --version 2.4.0

Then use whichever extensions (filters) you need.

Extensions (Filters) use

Ensure your API actions and parameters are decorated with explicit "Http" and "From" (optional) bindings.

[HttpPost]
public void CreateProduct([FromBody]Product product)
...
[HttpGet]
public IEnumerable<Product> SearchProducts([FromQuery]string keywords)
...

In the Configure method, insert middleware to expose the generated Swagger as JSON endpoint(s):

app.UseSwagger();

Optionally, insert the swagger-ui middleware if you want to expose interactive documentation, specifying the Swagger JSON endpoint(s) to power it from:

app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});
  1. Fix enums in OpenApi document:
using Unchase.Swashbuckle.AspNetCore.Extensions.Extensions;
using Unchase.Swashbuckle.AspNetCore.Extensions.Filters;
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddControllers();

    // Register the Swagger generator
    services.AddSwaggerGen(options =>
    {
        options.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });

        // use it if you want to hide Paths and Definitions from OpenApi documentation correctly
        options.UseAllOfToExtendReferenceSchemas();

        // if you want to add xml comments from summary and remarks into the swagger documentation, first of all add:
        // you can exclude remarks for concrete types
        var xmlFilePath = Path.Combine(AppContext.BaseDirectory, "WebApi3.1-Swashbuckle.xml");
        options.IncludeXmlCommentsWithRemarks(xmlFilePath, false,
            typeof(ComplicatedClass),
            typeof(InnerEnum));

        // or add without remarks
        //options.IncludeXmlComments(xmlFilePath);

        // if you want to add xml comments from inheritdocs (from summary and remarks) into the swagger documentation, add:
        // you can exclude remarks for concrete types
        options.IncludeXmlCommentsFromInheritDocs(includeRemarks: true, excludedTypes: typeof(string));

        // Add filters to fix enums
        // use by default:
        //options.AddEnumsWithValuesFixFilters();

        // or configured:
        options.AddEnumsWithValuesFixFilters(services, o =>
        {
            // add schema filter to fix enums (add 'x-enumNames' for NSwag or its alias from XEnumNamesAlias) in schema
            o.ApplySchemaFilter = true;

            // alias for replacing 'x-enumNames' in swagger document
            o.XEnumNamesAlias = "x-enum-varnames";

            // alias for replacing 'x-enumDescriptions' in swagger document
            o.XEnumDescriptionsAlias = "x-enum-descriptions";

            // add parameter filter to fix enums (add 'x-enumNames' for NSwag or its alias from XEnumNamesAlias) in schema parameters
            o.ApplyParameterFilter = true;

            // add document filter to fix enums displaying in swagger document
            o.ApplyDocumentFilter = true;

            // add descriptions from DescriptionAttribute or xml-comments to fix enums (add 'x-enumDescriptions' or its alias from XEnumDescriptionsAlias for schema extensions) for applied filters
            o.IncludeDescriptions = true;

            // add remarks for descriptions from xml-comments
            o.IncludeXEnumRemarks = true;

            // get descriptions from DescriptionAttribute then from xml-comments
            o.DescriptionSource = DescriptionSources.DescriptionAttributesThenXmlComments;

            // new line for enum values descriptions
            // o.NewLine = Environment.NewLine;
            o.NewLine = "\n";

            // get descriptions from xml-file comments on the specified path
            // should use "options.IncludeXmlComments(xmlFilePath);" before
            o.IncludeXmlCommentsFrom(xmlFilePath);
            // the same for another xml-files...
        });
    });
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc();

    services.AddSwaggerGen(options =>
    {
        options.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });

        // if you want to add xml comments into the swagger documentation, first of all add:
        var filePath = Path.Combine(AppContext.BaseDirectory, "WebApi3.1-Swashbuckle.xml");
        options.IncludeXmlComments(filePath);

        // Add filters to fix enums
        options.AddEnumsWithValuesFixFilters(true);

        // or custom use:
        //options.SchemaFilter<XEnumNamesSchemaFilter>(true); // add schema filter to fix enums (add 'x-enumNames' for NSwag) in schema
        //options.ParameterFilter<XEnumNamesParameterFilter>(true); // add parameter filter to fix enums (add 'x-enumNames' for NSwag) in schema parameters
        //options.DocumentFilter<DisplayEnumsWithValuesDocumentFilter>(true); // add document filter to fix enums displaying in swagger document
    });
}
  1. Hide Paths and Definitions from OpenApi documentation without accepted roles:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    ...

    services.AddSwaggerGen(options =>
    {
        ...

        // remove Paths and Defenitions from OpenApi documentation without accepted roles
        options.DocumentFilter<HidePathsAndDefinitionsByRolesDocumentFilter>(new List<string> { "AcceptedRole" });
    });
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    //...    

    // enable middleware to serve generated Swagger as a JSON endpoint.
    app.UseSwagger(c =>
    {
        c.PreSerializeFilters.Add((openApiDoc, httpRequest) =>
        {
            // remove Paths and Components from OpenApi documentation for specific controller action without accepted roles
            openApiDoc.RemovePathsAndComponentsWithoutAcceptedRolesFor<SomeController>(controller => nameof(controller.SomeAction), new List<string> {"AcceptedRole"});

            // or
            //openApiDoc.RemovePathsAndComponentsWithoutAcceptedRolesFor<SomeController>(nameof(SomeController.SomeAction), new List<string> { "AcceptedRole" });


            // remove Paths and Components from OpenApi documentation for all controller actions without accepted roles
            openApiDoc.RemovePathsAndComponentsWithoutAcceptedRolesForController<AnotherController>(new List<string> {"AcceptedRole"});

            // or you can get accepted roles by httpRequest like this:
            //openApiDoc.RemovePathsAndComponentsWithoutAcceptedRolesForController<AnotherController>(GetAcceptedRolesByRemoteIp(httpRequest.HttpContext.Connection.RemoteIpAddress));
        });
    });

    //...
}

Validated actions must be annotated with the one of HttpMethodAttribute (HttpGetAttribute, HttpPostAttribute, HttpDeleteAttribute, HttpPutAttribute, HttpPatchAttribute) attributes.

  1. Append action count into the SwaggetTag's descriptions in OpenApi document:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    ...

    services.AddSwaggerGen(options =>
    {
        ...

        // enable openApi Annotations
        options.EnableAnnotations();

        // add action count (with message template) into the SwaggerTag's descriptions
        // you can use it after "HidePathsAndDefinitionsByRolesDocumentFilter"
        options.DocumentFilter<AppendActionCountToTagSummaryDocumentFilter>("(count: {0})");

        ...
    });
}

In the controller need to use SwaggerTag attribute:

using Swashbuckle.AspNetCore.Annotations;
[SwaggerTag("Controller for todo")]
public class TodoController : ControllerBase
...
  1. Change all responses for specific HTTP status codes in OpenApi document:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    ...

    services.AddSwaggerGen(options =>
    {
        ...

        // change responses for specific HTTP status code ("200")
        options.ChangeAllResponsesByHttpStatusCode(
            httpStatusCode: 200,
            responseDescription: "200 status code description",
            responseExampleOption : ResponseExampleOptions.AddNew, // add new response examples
            responseExample: new TodoItem { Tag = Tag.Workout, Id = 111, IsComplete = false, Name = "test" }); // some class for response examples
        
        // change responses for specific HTTP status code ("400" (HttpStatusCode.BadRequest))
        options.ChangeAllResponsesByHttpStatusCode(
            httpStatusCode: HttpStatusCode.BadRequest,
            responseDescription: "400 status code description",
            responseExampleOption: ResponseExampleOptions.Clear, // claer response examples
            responseExample: new ComplicatedClass()); // some class for response examples
        
        // change responses for specific HTTP status code ("201" (StatusCodes.Status201Created))
        options.ChangeAllResponsesByHttpStatusCode(
            httpStatusCode: StatusCodes.Status201Created,
            responseDescription: "201 status code description",
            responseExampleOption: ResponseExampleOptions.None, // do nothing with response examples
            responseExample: new ComplicatedClass()); // some class for response examples

        ...
    });
}
  1. Order tags by name in OpenApi document:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    ...

    services.AddSwaggerGen(options =>
    {
        ...

        // order tags by name
        options.DocumentFilter<TagOrderByNameDocumentFilter>();

        ...
    });
}
  1. Add xml comments from summary and remarks into the swagger documentation:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    ...

    services.AddSwaggerGen(options =>
    {
        ...

        // add xml comments from summary and remarks into the swagger documentation
        options.IncludeXmlCommentsWithRemarks("<xml_File_Full_Path>");

        // add xml comments from summary and remarks into the swagger documentation
        // with excluding remarks for concrete types (since v2.4.1)
        var xmlFilePath = Path.Combine(AppContext.BaseDirectory, "WebApi3.1-Swashbuckle.xml");
        options.IncludeXmlCommentsWithRemarks(xmlFilePath, false,
            typeof(ComplicatedClass),
            typeof(InnerEnum));

        ...
    });
}
  1. Add xml comments from <inheritdoc/> (from summary and remarks) into the swagger documentation:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    ...

    services.AddSwaggerGen(options =>
    {
        ...

        // add xml comments from inheritdocs (from summary and remarks) into the swagger documentation, add:
        // with excluding concrete types
        options.IncludeXmlCommentsFromInheritDocs(includeRemarks: true, excludedTypes: typeof(string));

        ...
    });
}

Builds status

StatusValue
BuildBuild status
TestsBuild Tests
Buid HistoryBuild history
GitHub ReleaseGitHub release
GitHub Release DateGitHub Release Date
GitHub Release DownloadsGithub Releases
Nuget VersionNuGet Version
Nuget DownloadsNuget Downloads

Features

Fix enums

Hide Paths and Defenitions from OpenApi documentation

Append action count into the SwaggetTag's descriptions

Append action count

You should use SwaggerTagAttribute for controllers:

[SwaggerTag("SamplePerson description")]
public class SamplePersonController : ControllerBase
{
    ...
}

Change responses for specific HTTP status codes

For example:

Change responses

Add xml comments from summary and remarks into the swagger documentation

Add xml comments from summary and remarks

For code:

/// <summary>
/// Inner class
/// </summary>
/// <remarks>
/// Inner class remarks - class
/// </remarks>
public class InnerClass
{
    /// <summary>
    /// List of inner enums
    /// </summary>
    /// <remarks>
    /// List of inner enums remarks - property
    /// </remarks>
    public List<InnerEnum> InnerEnum { get; set; }

    /// <summary>
    /// Second inner class
    /// </summary>
    /// <remarks>
    /// Second inner class remarks - property
    /// </remarks>
    public SecondInnerClass<SecondInnerEnum> SecondInnerClass { get; set; }
}

/// <summary>
/// Inner enum
/// </summary>
/// <remarks>
/// Inner enum remarks - enum
/// </remarks>
public enum InnerEnum
{
    /// <summary>
    /// Inner enum value
    /// </summary>
    /// <remarks>
    /// Inner enum value remarks
    /// </remarks>
    Value = 1
}

/// <summary>
/// Second inner class
/// </summary>
/// <remarks>
/// Second inner class remarks - class
/// </remarks>
public class SecondInnerClass<T> where T : Enum
{
    /// <summary>
    /// Second inner enum
    /// </summary>
    /// <remarks>
    /// Second inner enum remarks - property
    /// </remarks>
    public T InnerEnum { get; set; }
}

/// <summary>
/// Second inner enum
/// </summary>
/// <remarks>
/// Second inner enum remarks - enum
/// </remarks>
public enum SecondInnerEnum
{
    /// <summary>
    /// Second inner enum value
    /// </summary>
    /// <remarks>
    /// Second inner enum value remarks
    /// </remarks>
    Value = 0
}

Add xml comments from <inheritdoc/> (from summary and remarks) into the swagger documentation

Add xml comments from ingeritdoc

For code:

/// <inheritdoc cref="IInheritDocClass"/>
public class InheritDocClass : IInheritDocClass
{
    /// <inheritdoc/>
    public string Name { get; set; }

    /// <inheritdoc/>
    public string Common { get; set; }

    /// <inheritdoc/>
    public InheritEnum InheritEnum { get; set; }
}

/// <summary>
/// InheritDocClass - inheritdoc
/// </summary>
/// <remarks>
/// InheritDocClass remarks - inheritdoc
/// </remarks>
public interface IInheritDocClass : IInheritDocCommon
{
    /// <summary>
    /// Name - inheritdoc
    /// </summary>
    /// <remarks>
    /// Name remarks - inheritdoc
    /// </remarks>
    public string Name { get; set; }
}

/// <summary>
/// IInheritDocCommon interface
/// </summary>
/// <remarks>
/// IInheritDocCommon interface remarks
/// </remarks>
public interface IInheritDocCommon
{
    /// <summary>
    /// Common - inheritdoc (inner)
    /// </summary>
    /// <remarks>
    /// Common remarks - inheritdoc (inner)
    /// </remarks>
    public string Common { get; set; }

    /// <summary>
    /// InheritEnum - inheritdoc (inner)
    /// </summary>
    public InheritEnum InheritEnum { get; set; }
}

/// <summary>
/// Inherit enum - enum
/// </summary>
/// <remarks>
/// Inherit enum remarks - enum
/// </remarks>
public enum InheritEnum
{
    /// <summary>
    /// Inherit enum Value
    /// </summary>
    /// <remarks>
    /// Inherit enum Value remarks
    /// </remarks>
    Value = 0
}

HowTos

Roadmap

See the changelog for the further development plans and version history.

Feedback

Please feel free to add your request a feature or report a bug. Thank you in advance!

Thank me!

If you like what I am doing and you would like to thank me, please consider:

Buy me a coffe!

Thank you for your support!


Copyright © 2019 Nikolay Chebotov (Unchase) - Provided under the Apache License 2.0.