Customizing swagger API Documentation in .NET Core

Customizing Swagger API ASPNET Core 31 and NET 50

I was wondering if the swagger API definition (service documentation) can be modified programmatically. After a few hours of analysis, I found there are ways to do so and one can modify swagger definitions easily.

A swagger definition can be customized at the Operation level or at Service i.e. Controller level,

  1. Operation level customization
  2. Documents level customization

Today in this article, we will cover below aspects,

If you are looking for basic details like how to add Swagger API documentation in ASP.NET Core 2.2, I would recommend you to refer to the below article on basics,

Swagger or OpenAPI specification is an attempt to create a universal description for REST API.

This specification provides the advantage of understanding the REST services easily (especially if developers are consuming any new web API ) plus helps provide easily ready documentation and details of capabilities an organization owns.

Swagger is all about REST service documentation based on Open API specifications.

Here is the example I am giving, not everything will suffice your requirements but this example will help you understand and let you perform customization as per your needs.

ASP.NET Core 3.1 or .NET 5 or 6

Please visit the below article for details

  • Using IOperationFilter or IDocumentFilter in ASP.NET Core 3.1 and .NET 5.0
  • Getting Started

    Please create an API using the ASP.NET Core of your choice.

    Here in the below example, I am using .NET Core 2.2, however, you can use any version of .NET Core like 2.2.

    The below techniques work perfectly fine for all .NET Core versions < 2.2.

    After adding basic swagger support below is the output generated for our sample API definition. Please visit Swagger API documentation in .NET Core 2.2 for enabling swagger to an API which is simply a 2-3 steps process.

    After adding swagger successfully, below is the output,

    Documents level customization

    Let’s first try customizing the Service definition followed by updating API documentation.

    Document Filters

    Let’s look at how to customize swagger documentation at the root document level. At a document level you can control service-level descriptions, most importantly Info object wherein you provide details about service title, version, and licensing details.

    blank

    IDocumentFilter Interface

    Here I am trying to add additional details to the existing service’s definitions. Let’s create a class SwagggerCustomDocumentAttribute using IDocumentFilter and override the method Apply(). Here I am updating the contact details of the service.

     public class SwagggerCustomDocumentAttribute : IDocumentFilter
        {
            public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
            {
                Contact contact = new Contact { Email = "digital@thecodebuzz.com", Url = "www.thecodebuzz.com" };
                swaggerDoc.Info.Contact = contact;
            }
        }
    
    

    Finally, we need to enable this SwagggerCustomDocumentAttribute class attribute within services extending the swagger feature as shown below,

    blank

    If you have multiple services requiring similar changes, then best practice would be to create a .NET Core library and use the same references everywhere. This way common logic can be centralized by moving it to assembly and extending swagger through services.

    blank

    Operation level customization

    Let’s try customizing operation level definition,

    Operation Filters

    Operation filters can be implemented using the IOperationFilter interface. One can retrieve ApiDescription for relevant information like attribute, and route info at an instance or method level.


    IOperationFilter Interface

    Let’s see an example of retrieving operation details and setting up additional HTTP response codes to all API where CustomAttribute is defined.

    You can address multiple requirements using IOperaitonfilter but today in this article we shall see basic usage.

    public class SwagggerCustomOperationAttribute : IOperationFilter
        {
            public void Apply(Operation operation, OperationFilterContext context)
            {
    
                var authAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true)
                                       .Union(context.MethodInfo.GetCustomAttributes(true))
                                       .OfType<customattribute>();
                if (authAttributes.Any())
                {
                 //add your logic here
                }
            }
        }
    
    

    Here we shall use operations filter context to get details about operations and their declaring types.

            public void ConfigureServices(IServiceCollection services)
            {
                services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
                services.AddSwaggerGen(c =>
                {
                    c.SwaggerDoc("v1", new Info { Title = "MyTestService", Version = "v1" });
                    c.OperationFilter<SwagggerCustomoperationattribute>();
                    
                });
            }
    
    

    Let’s look at API where the API response type i.e [ProducesResponseType] doesn’t exist. If API is returning multiple ActionResult [ProducesResponseType] attributes helps to produce more descriptive response details for a developer to understand the API using Swagger.   [ProducesResponseType] also shows the known types and HTTP status codes to be returned by the action.

    Generally, to have more descriptive return types, users tend to add [ProducesResponseType] as below,

    blank

    The above responses type are more generic. All API or (90%) of your API needs need to be attributed to those as a good practice.

    IOperationFilter interface can be used to automate this into a centralized location. Below is an example of how to achieve that,

    public class SwagggerCustomOperationAttribute : IOperationFilter
        {
            public void Apply(Operation operation, OperationFilterContext context)
            {
    
                var authAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true)
                                       .Union(context.MethodInfo.GetCustomAttributes(true))
                                       .OfType<customattribute>();
                if (authAttributes.Any())
                {
                operation.Responses.Add("400", new Response { Description = "Bad Request" });
                operation.Responses.Add("404", new Response { Description = "Resouce Not Found" });
                operation.Responses.Add("500", new Response { Description = "Internal Server Error" });
                }
            }
        }
    

    So now this is how we simplified the API attribute

    blank

    Once API gets executed, the Swagger definition updated will be shown below highlighted,

    blank

    So we are able to add response types to API without having to modify the code for individual API and without repeating the code. This approach is simpler and logic can be centralized if needed for reuse in all other API. This technique can be used to move the generic HTTP status code to commonplace.

    Please note the above techniques are just to demonstrate to you the ability of these few Swagger Interfaces. You may or may not find the need to do the above requirement.

    You can use [ProducesResponseType] anyway for other specific requirements.

    Other references:

    Summary

    Swagger API documentation Customization can help you modify the swagger definition as per your organization’s requirements. IOperationFilter and IDocumentFilter interfaces allow us to customize swagger documentation to all possible extents.



    Please bookmark this page and share it with your friends. Please Subscribe to the blog to receive notifications on freshly published(2024) best practices and guidelines for software design and development.



    6 thoughts on “Customizing Swagger API documentation in .NET Core

    1. Hi,
      We all know that we can specify number of servers in Swagger.
      Is that possible to redirect only one endpoint into another server?
      Thanks in advance

    2. Thanks for your response, appreciate it. Do you have a code snippet that can filter out methods based on ASPNETCORE_ENVIRONMENT or using the filters IDocumentFilter and IOperation as I am struggling to get around with it.

    3. This is really helpful. I now have a requirement to hide certain endpoints in our Prod environment but display all endpoints in DEV and UAT environments.
      Can you please let me know how can we populate Swagger Documentation based on different environments?

      Thanks in advance.

      1. Hi Vipul, Thanks for your query. A bit late in replying to you. However, as I understand your requirements, you can implement these multiple ways. I see if you already using ‘ASPNETCORE_ENVIRONMENT’ you can these flags into your logic to display methods specific to that environment.

        Also if using any other way to identify your environment the same approach can be followed.
        I also see your requirement can also be addressed using feature toggle

        IDocumentFilter and IOperation filter let you read through Class and its members including method or properties.

        Hope this helps you.

    Leave a Reply

    Your email address will not be published. Required fields are marked *