In this article, we will explore the two popular libraries for generating OpenAPI documentation in C#: Swashbuckle and NSwag. We’ll compare their features, ease of use, and other factors that will help us choose the best one for our projects.
Let’s start.
What are Swashbuckle and NSwag Used for?
Swashbuckle and NSwag are two popular libraries in the C# ecosystem that we can use to generate OpenAPI documentation.
OpenAPI, formerly known as Swagger, is a widely adopted standard for RESTful API documentation. We can use it to describe the structure of our APIs, making it easier for others to understand and consume them. By using it we can generate interactive API documentation that allows consumers to explore and test our API endpoints.
What’s more, the OpenAPI specification also allows us to generate client libraries for various programming languages, making it easier to integrate our APIs into different applications.
Let’s dive into each of them and understand their differences.
What is Swashbuckle?
We will start with Swashbuckle, which is a popular open-source library for generating API documentation for ASP.NET Core applications.
We can use it to automatically generate an OpenAPI specification based on our controllers, routes, and models, allowing us to serve up interactive, browser-based documentation with minimal effort.
Now, let’s have a look at an example of generated documentation:
On top of that, it offers various customization options, such as adding XML comments to generated documentation, modifying operation tags and descriptions, and customizing UI appearance.
Example Usage of Swashbuckle
First, we need to install Swashbuckle. To do that we simply need to run the Nuget command:
Install-Package Swashbuckle.AspNetCore -Version 6.5.0
Or we can use the .Net CLI command:
dotnet add package Swashbuckle.AspNetCore
Then we have to register Swagger in ConfigurationServices
method in Startup.cs
file:
public void ConfigureServices(IServiceCollection services) { // Add Swashbuckle to our services services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" }); }); services.AddControllers(); }
This will add the Swagger generator to our collection of services.
After that, we need to enable middleware to serve generated Swagger as a JSON endpoint and Swagger UI. We can do this by modifying our Configure
method:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // Enable middleware to serve generated Swagger as a JSON endpoint and Swagger UI app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); }); }
At this point, we are ready to start utilizing Swagger in our project.
What is NSwag?
Now let’s talk about NSwag, which is another powerful library for generating OpenAPI Specification documents and client code from .NET applications.
It supports both .NET Framework and .NET Core and offers additional features like code generation.
As we can read on the GitHub page of the project, NSwag is intended to combine functionalities of two other libraries: Swashbuckle for OpenAPI generation and AutoRest for client generation.
Example Usage of NSwag
To install it we simply need to run this command:
Install-Package NSwag.AspNetCore -Version 13.18.2
Alternatively, we can use the .Net CLI command:
dotnet add package NSwag.AspNetCore
Once we have NSwag installed we have to add it to our services collection within the ConfigurationServices
method in our Startup.cs
file:
public void ConfigureServices(IServiceCollection services) { // Register the NSwag services services.AddOpenApiDocument(config => { config.DocumentName = "v1"; config.Title = "My API"; config.Version = "v1"; }); services.AddControllers(); }
After that, we have to modify our Configure
method:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { app.UseOpenApi(); app.UseSwaggerUi3(); }
Once we complete these steps we are ready to use NSwag.
Now that we know some basic information about both libraries, we can take a deep dive into a comparison of the features they provide.
API Documentation Generation
We will start with the primary feature, which is API documentation generation.
It’s no surprise that both Swashbuckle and NSwag excel at generating API documentation based on our controllers and actions. They inspect our code to create an OpenAPI specification document, which we can serve as interactive documentation through the Swagger UI or ReDoc UI.
Additionally, both libraries can provide documentation in either JSON or YAML formats.
In Swashbuckle we can achieve that by modifying the Configure
method:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // Enable middleware to serve generated Swagger as a JSON endpoint and Swagger UI app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.yaml", "My API V1"); }); }
As we can see, we just need to specify the .yaml
extension in our SwaggerEndpoint
configuration.
And respectively for NSwag:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { app.UseOpenApi(p => p.Path = "/swagger/v1/swagger.yaml"); app.UseSwaggerUi3(p => p.DocumentPath = "/swagger/v1/swagger.yaml"); }
Here, we need to do a bit more work.
Firstly, we modify the Path
property specifying the .yaml
format when calling UseOpenApi
method. Then in the same way we need to modify our DocumentPath
property when we call the UseSwaggerUi3
method.
All in all, both libraries allow API consumers to explore and test our API endpoints in a user-friendly manner. And if the only feature we need is generating documentation for our APIs, then either of these libraries is a solid choice.
Swagger UI Customization
Swagger UI is a popular interactive documentation tool we can customize to match our API’s branding or style requirements. Both Swashbuckle and NSwag support Swagger UI customization.
If we would like to modify it we have a few options to choose from.
We can copy the content of the Swagger UI repository to the wwwroot/swagger/ui
folder in our project and modify the required files.
Or we can simply inject the style sheet directly into Swagger UI, like so:
app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); c.InjectStylesheet("/custom.css"); });
And since this is a feature of Swagger UI itself, it will work the same way for both Swashbuckle and NSwag.
Or if we prefer, we can also use ReDoc UI.
First, we need to add a dependency to the Swashbuckle.AspNetCore.ReDoc
package. Then we need to call app.UseRedoc()
instead of app.UseSwaggerUi()
.
Lastly, because ReDoc is exposed via/api-docs
we can change this when enabling middleware by setting RoutePrefix
:
app.UseReDoc(c => c.RoutePrefix = "swagger" );
In contrast, this transition is much easier with NSwag. We simply need to call app.UseReDoc()
instead of app.UseSwaggerUi3()
and we are done.
As a result, we can see ReDoc UI:
Code generation
Code generation is a feature that allows us to quickly generate clients for our APIs for different programming languages.
While this feature is useful and can speed up our development process, Swashbuckle does not have built-in support for generating client code directly. It can be used in combination with other tools or libraries that consume OpenAPI specification files to generate client code.
NSwag, on the other hand, provides us with a set of code generation features and can generate client code for C# or TypeScript.
In addition, it offers multiple ways to generate code, such as using the NSwagStudio GUI, the NSwag CLI, or integrating NSwag directly into our project as a middleware or build tool.
Let’s take a look at how we can easily generate a TypeScript client using NSwagStudio. We just need to launch it and provide it with the URL to our Swagger documentation swagger.json
file:
Then select the output format and click Generate Outputs
:
And with those simple steps, we have our client ready to be used in consumer applications.
Support of Authentication Configuration
To take things to the next level, let’s have a look at how we might configure a layer of authentication to secure our API.
Both Swashbuckle and NSwag support various authentication configurations, allowing us to secure our API and its documentation.
Swashbuckle provides support for several authentication methods, including OAuth2, API keys, and JWT (JSON Web Tokens).
Now, let’s take a look at a short example.
We will modify our Startup.cs
file and set up authentication for our API documentation in Swashbuckle using JWT:
public void ConfigureServices(IServiceCollection services) { //Setup JWT Authentication services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { var key = Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]); options.TokenValidationParameters = new TokenValidationParameters { ValidIssuer = Configuration["Jwt:Issuer"], ValidAudience = Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey(key), ValidateIssuer = false, ValidateAudience = false, ValidateLifetime = true, ValidateIssuerSigningKey = true }; }); // Add Swashbuckle to our services services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" }); // Configure authentication for Swagger c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "JWT Authorization header using the Bearer scheme.", Type = SecuritySchemeType.Http, Scheme = "bearer" }); c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } }, Array.Empty<string>() } }); }); services.AddControllers(); }
The first thing we do is configure JWT authentication. We do this by registering JWT middleware using the AddAuthentication
method. Next, we use the AddJwtBearer
method to enable JWT authentication and configure bearer options.
Then, we modify the Swashbuckle configuration to enable authentication using the bearer schema by calling AddSecurityDefinition
and AddSecurityRequirement
methods.
NSwag supports a similar range of authentication methods as Swashbuckle, including OAuth2, API keys, and JWT.
And again, let’s check out a short example.
We can set up authentication for our API documentation in NSwag by modifying our Startup.cs
file and adding OAuth2 authentication:
public void ConfigureServices(IServiceCollection services) { //Configure OAuth2 authentication services.AddAuthentication(options => { options.DefaultAuthenticateScheme = "Bearer"; options.DefaultChallengeScheme = "Bearer"; }) .AddOpenIdConnect("Bearer", options => { // Configure OpenID Connect options here options.Authority = Configuration("OAuth2:Authority"); options.ClientId = Configuration("OAuth2:ClientId"); options.ClientSecret = Configuration("OAuth2:ClientSecret"); options.ResponseType = OpenIdConnectResponseType.Code; options.Scope.Clear(); options.Scope.Add("openid"); options.Scope.Add("profile"); options.Scope.Add("email"); options.Scope.Add("api"); options.SaveTokens = true; }); // Add NSwag to our services services.AddOpenApiDocument(config => { config.DocumentName = "v1"; config.Title = "My API"; config.Version = "v1"; // Configure OAuth2 authentication for NSwag config.AddSecurity("OAuth2", Enumerable.Empty<string>(), new OpenApiSecurityScheme { Type = SecuritySchemeType.OAuth2, Flows = new OpenApiOAuthFlows { AuthorizationCode = new OpenApiOAuthFlow { AuthorizationUrl = Configuration("OAuth2:AuthorizationUrl"), TokenUrl = Configuration("OAuth2:TokenUrl"), Scopes = new Dictionary<string, string> { { "openid", "OpenID Connect" }, { "profile", "User profile" }, { "email", "User email" }, { "api", "Access to API" } } } } }); config.OperationProcessors.Add(new OperationSecurityScopeProcessor("OAuth2")); }); services.AddControllers(); }
Firstly, we configure the authentication scheme through the use of the OpenID Connect authentication middleware.
Then, we modify the NSwag configuration to enable OAuth2 authentication with our AddSecurity
method, and utilize OperationProcessors
to implement OAuth2.
Now, when we access the UI generated by NSwag, we will see an Authorize
button that allows users to authenticate using our OAuth2 provider. Once authenticated, users can automatically (and securely!) make API calls with the appropriate access token.
Performance Comparison
Both Swashbuckle and NSwag have similar performance profiles, meaning that both libraries are suitable for small to large projects.
We have to remember that both libraries focus on generating API documentation and client code, which are typically one-time or infrequent operations during the development process.
Thus, the performance overhead introduced by these libraries is minimal, as they primarily generate static documentation and client code. Therefore there is a slight overhead during app startup, but after that, it is usually negligible.
And indeed, we use the BenchmarkDotNet package to investigate those differences:
| Method | Mean | Error | StdDev | Allocated | |--------------------------|---------:|----------:|---------:|-----------:| | Swashbuckle_PostResponse | 6.861 ms | 0.6065 ms | 1.788 ms | 919.91 KB | | NSwag_PostResponse | 8.287 ms | 0.9454 ms | 2.728 ms | 1156.43 KB | | Swashbuckle_GetResponse | 5.833 ms | 0.4129 ms | 1.205 ms | 958.58 KB | | NSwag_GetResponse | 8.740 ms | 1.1480 ms | 3.312 ms | 1060.64 KB |
As we can see the difference is less than 2ms in favor of Swashbuckle on both POST and GET endpoints.
It’s worth noting that NSwag’s code generation feature might add additional overhead, especially when generating code for multiple languages or large APIs. However, due to its infrequent usage, it is normally not a consideration for application runtime performance.
Ease of Use
Next, let’s look at how easy is it to use each library.
Both Swashbuckle and NSwag provide us with a straightforward setup process, and our earlier setup examples demonstrate how quickly they allow us to get started.
Here, though, we encounter one of the biggest advantages of Swashbuckle. Since .NET 6 and Visual Studio 2022, Swashbuckle is natively supported by built-in project templates. This means that we can easily add Swagger to our APIs using the new project creator.
When we create new API projects we simply need to tick a checkbox next to the Enable OpenApi support
option:
And as simple as that, a Swashbuckle dependency will be added to our project, and all necessary configurations applied to our code.
On the other hand, if we want to use NSwag, the configuration process is a manual one (albeit not too tedious).
Compatibility Considerations
Another point to consider when deciding whether we should use Swashbuckle or NSwag is compatibility with different versions of the .NET Framework.
Swashbuckle supports both ASP.NET Core and the older ASP.NET also known as ASP.NET MVC/WebAPI. However, the integration process and package names are different for each version. For ASP.NET Core, we would use the Swashbuckle.AspNetCore
package, while for the older ASP.NET MVC/WebAPI projects, we should use the Swashbuckle
package.
We have a similar situation with NSwag, it is compatible with both .NET Framework and .NET Core. And we have to reference the appropriate package for our needs. For ASP.NET Core, we would use the NSwag.AspNetCore
package, while for the older ASP.NET MVC/WebAPI projects, we should use the NSwag.AspNet.WebApi
package.
So, both Swashbuckle and NSwag support ASP.NET Core and the older ASP.NET MVC/WebAPI. Both offer impressive versatility for projects based on different .NET frameworks.
Community Support
Finally – and very importantly – we come to community support. Even the greatest library will have limited usefulness without the support of the community and their ongoing development, enhancement, troubleshooting, and bug-fixing efforts. These are indispensable, especially when we are talking about open-source projects.
Swashbuckle enjoys more community support because of its maturity. To this day it has been downloaded over 324 million times.
It has a large and active community that contributes to the project, provides support, and shares knowledge. The main GitHub repository for Swashbuckle.AspNetCore
has over 4.8 thousand stars and over 1.2 thousand forks. And what’s more, it reports that almost 450 thousand projects are using it.
There are numerous blog posts, tutorials, and Stack Overflow answers available that cover various aspects of Swashbuckle usage and configuration. If we encounter issues or need help, we can often find answers on Stack Overflow, GitHub issues, or other community forums.
And as we have noted, even Microsoft provides native support for it in Visual Studio 2022.
On the other hand, NSwag is gaining popularity and has an active community that continues to help with its development.
While it may not be as widely known as Swashbuckle, it still has a strong and active community. The main GitHub repository for NSwag has over 5.9 thousand stars and 1.1 thousand forks. But reports that only over 2300 project uses it.
Similarly to Swashbuckle, there are numerous blog posts, tutorials, and Stack Overflow answers available that cover various aspects of NSwag usage and configuration.
All in all, both libraries have a good number of contributors and resources available for learning and troubleshooting. Swashbuckle is more widely-known and has a larger community, which may result in slightly more resources and community support. However, NSwag also has a strong and active community, making it a viable choice as well.
Whilst NSwag may look great, in practice we have found a number of issues with the code generation. A bigger problem, however, is that it doesn’t seem to be open for maintainance.
There are thousands of bug reports and questions, and pull requests outstanding for over a year.
It looks like only the author is able to do any work on it, and that is very limited.
Of course, you can fork it to fix any bugs which are relevant to you, which we have done.