IOperationFilter and IDocumentFilter in ASP.NET Core
In this article, we will understand the Swagger interfaces IOperationFilter and IDocumentFilter in ASP.NET Core 3.1 services introduced based on OpenAPI specification i.e swagger v3.0
I already talked about these two interfaces in my previous article supporting ASP.NET Core 2.2 which was based on swagger v2.0 specification.
With the many recent improvements to the ASP.NET Core 3.1 and above, these Interfaces also got updated which includes a few breaking changes. I shall be highlighting those generic changes in this article.
If you are looking for basic details like how to add Swagger API documentation in .NET Core, I would recommend you to read the below article on basics,
Swagger or Open API 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 given service owns.
Today in this article, we will cover below aspects,
A swagger definition can be customized at the Service or Operation level.
Let’s see a few examples. Here in these examples, not everything will suffice for your requirements but it will help you understand and let you perform customization as per your needs.
Getting Started
Create ASP.NET Core 3.1 API
Let’s first try customizing the Service definition followed by updating API documentation.
IDocumentFilter
Let’s look at how to customize swagger documentation at the root document level.
Using IDocumentFilter provides more control over document definition before submitting the generated document to the user using the Swagger UI tool.
Global API Metadata
We can control service-level descriptions, most importantly OpenApiInfo objects wherein you can provide details about service title, version, and licensing details.
OpenApiDocument objects can be defined and set with customized details and presented to the user.
Create CustomSwaggerDocumentAttribute class using IDocumentFilter and override method Apply() as below,
public class CustomSwaggerDocumentAttribute : IDocumentFilter
{
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
swaggerDoc.Info = new OpenApiInfo
{
Title = "TheCodeBuzz Service",
Version = "v1",
Description = "Service of Open community",
TermsOfService = new Uri("http://tempuri.org/terms"),
Contact = new OpenApiContact
{
Name = "TheCodeBuzz",
Email = "info@thecodebuzz.com"
},
License = new OpenApiLicense
{
Name = "Apache 2.0",
Url = new Uri("http://www.thecodebuzz.com")
}
};
}
}
Finally, we need to enable this CustomSwaggerDocumentAttribute within services extending swagger feature as shown below,
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.DocumentFilter<CustomSwaggerDocumentAttribute>();
c.OperationFilter<CustomHeaderSwaggerAttribute>();
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
}
The above logic further can be moved to Service collection.
This way common logic can be centralized by moving it to assembly and extending swagger through services.
Below is the generated swagger documentation,
Operation level customization
Let’s try customizing operation level definition,
IOperationFilter
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 can be used to address multiple requirements.
Operation Metadata
Let’s see an example of retrieving operation details and setting up a custom header swagger API.
We shall be making use of OpenApiOperation and OpenApiParameter objects to define the metadata.
public class CustomHeaderSwaggerAttribute : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.Parameters == null)
operation.Parameters = new List<OpenApiParameter>();
operation.Parameters.Add(new OpenApiParameter
{
Name = "x-customHeader",
In = ParameterLocation.Header,
Required = true,
Schema = new OpenApiSchema
{
Type = "String"
}
});
}
}
Let’s add CustomHeaderSwaggerAttribute to swagger middleware.
services.AddSwaggerGen(c =>
{
c.DocumentFilter<CustomSwaggerDocumentAttribute>();
c.OperationFilter<CustomHeaderSwaggerAttribute>();
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
Finally Generated swagger documentation with customized metadata looks as below,
Other references:
Summary
IOperationFilter and IDocumentFilter interfaces allow us to customize and control the API metadata and define swagger documentation as per your requirements easily.
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.
The above is very usefull. Thank you for your post!
Do you know, if there is a way to add or remove swaggerdocuments based on a filter? Or another way of doing this runtime? (I have a database that holds information on which documents should be generated – one for each customertype.)
Hi Lotte,P – Thanks. Glad the article helped you!. Did you check this article for adding a filter Add/Hide OpenAPI Swagger based on Environment (DEV, TEST, PROD). Hope it helps you.
In that example you’re choosing which content to put in the one swaggerdocument.
In my scenario I have x documents and I want to add or remove hole documents.
The endpoints in the SwaggerUI can be fixes by implementing IConfigureOptions and create a middleware wrapper for SwaggerUIMiddleware. Then the SwaggerUIOptions will be re-configured. But I can’t find a way to make SwaggerGenerator reload the SwaggerGenOptions. Or another way of changing the SwaggerGeneratorOptions.SwaggerDocs dictionary after the initial configuration..
i dis all the changes as explained above but unable to get swagger interface. Note my dot net core version is 2.1 & i have used swasbuckle of 6.0.1 version.
Hey Tarun – Please make sure to use only compatible packages. .NET Core 2.1 and less version is more compatible with Swagger v2.0 specification and hence please try to use those supporting swashbuckle packages to avoid any issue.
I am unable to view your previous post.
Hello Patrick. I fixed the broken links. Thanks for letting me know. Appreciate it.