Swagger is more than just API documentation. It’s a tool that empowers developers to design, build, and test APIs with ease and efficiency.
The process of developing and testing APIs can be a daunting task. Especially when dealing with complex projects that involve multiple endpoints and teams. To simplify this process, the OpenAPI specification and its toolset, Swagger UI, have become increasingly popular among developers.

Swagger is an open-source set of tools. It allows developers to easily design, document, and consume RESTful web services. Swagger provides a standardized format for describing RESTful APIs. Also, known as the OpenAPI specification. which allows developers to generate client libraries, server stubs, and documentation automatically.
Swagger UI, a tool within the Swagger ecosystem, provides a user interface. It allows developers to visualize and interact with their API resources without writing any code. Using Swagger, developers can save time and improve collaboration by providing a common language and format for API development across teams.

Table of Contents
Add Swagger to Web API from NuGet Packages
To add Swagger to Web API project, the first step is to install the Swashbuckle.AspNetCore NuGet package. Here are the steps to follow:
From the Package Manager Console window:
- Go to View > Other Windows > Package Manager Console
- Navigate to the directory in which the
.csproj
file exists - Execute the following command:
Install-Package Swashbuckle.AspNetCore -Version 6.5.0
From the Manage NuGet Packages dialog:
- Right-click the project in Solution Explorer > Manage NuGet Packages
- Set the Package source to “nuget.org”
- Ensure the “Include prerelease” option is enabled
- Enter
"Swashbuckle.AspNetCore"
in the search box - Select the latest
"Swashbuckle.AspNetCore"
package from the Browse tab and click Install
After installation, the Swashbuckle.AspNetCore package will provide tools for adding Swagger documentation to your ASP.NET 7 Web API project.
Congratulations on successfully adding Swagger to your Web API project!
Add and configure Swagger middleware
Add the Swagger generator to the services collection in Program.cs
:
builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen();
Enable the middleware for serving the generated JSON document and the Swagger UI, also in Program.cs
:
if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); }
The code mentioned above includes a conditional check that adds the Swagger middleware to the pipeline only when the current environment is set to Development. This means that the Swagger UI will only be available during the development phase and not in production.
Additionally, the UseSwaggerUI
method call enables the Static File Middleware. Which is responsible for serving the Swagger UI HTML, CSS, and JavaScript files from the wwwroot folder. This allows the Swagger UI to be displayed in the browser by pointing it to the correct URL endpoint.
Launch the app and navigate to https://localhost:<port>/swagger/v1/swagger.json
. The generated document describing the endpoints appears as shown below.
{ "openapi": "3.0.1", "info": { "title": "API V1", "version": "v1" }, "paths": { "/api/Todo": { "get": { "tags": [ "Todo" ], "operationId": "ApiTodoGet", "responses": { "200": { "description": "Success", "content": { "text/plain": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ToDoItem" } } }, "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ToDoItem" } } }, "text/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ToDoItem" } } } } } } }, "post": { … } }, "/api/Todo/{id}": { "get": { … }, "put": { … }, "delete": { … } } }, "components": { "schemas": { "ToDoItem": { "type": "object", "properties": { "id": { "type": "integer", "format": "int32" }, "name": { "type": "string", "nullable": true }, "isCompleted": { "type": "boolean" } }, "additionalProperties": false } } } }
Customizing Swagger UI in ASP.NET Core
Swagger provides options for documenting the object model and customizing the UI to match your theme.
API info and description
The configuration action passed to the AddSwaggerGen
method adds information such as the author, license, and description.
In Program.cs
, import the following namespace to use the OpenApiInfo
class:
using Microsoft.OpenApi.Models;
Using the OpenApiInfo
class, modify the information displayed in the UI:
builder.Services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new OpenApiInfo { Version = "v1", Title = "ToDo API", Description = "An ASP.NET Core Web API for managing ToDo items", TermsOfService = new Uri("https://example.com/terms"), Contact = new OpenApiContact { Name = "Example Contact", Url = new Uri("https://example.com/contact") }, License = new OpenApiLicense { Name = "Example License", Url = new Uri("https://example.com/license") } }); });
The Swagger UI displays the version’s information:

XML comments
XML comments can be enabled with the following approaches:
- Right-click the project in Solution Explorer and select
Edit <project_name>.csproj
. - Add GenerateDocumentationFile to the
.csproj
file:
<PropertyGroup> <GenerateDocumentationFile>true</GenerateDocumentationFile> </PropertyGroup>
To make Swagger use the XML file generated in the previous steps, you need to configure it accordingly. Keep in mind that for non-Windows or Linux-based operating systems, file names and paths may be case-sensitive. For instance, a TodoApi.XML file may work on Windows, but not on CentOS.
builder.Services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new OpenApiInfo { Version = "v1", Title = "ToDo API", Description = "An ASP.NET Core Web API for managing ToDo items", TermsOfService = new Uri("https://example.com/terms"), Contact = new OpenApiContact { Name = "Example Contact", Url = new Uri("https://example.com/contact") }, License = new OpenApiLicense { Name = "Example License", Url = new Uri("https://example.com/license") } }); // using System.Reflection; var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename)); });
The code shown above uses Reflection to construct the XML file name that matches the web API project. The AppContext.BaseDirectory
property is utilized to create the path to the XML file. Some Swagger features (for example, schemata of input parameters or HTTP methods and response codes from the respective attributes) work without the use of an XML documentation file. For most features, namely method summaries and the descriptions of parameters and response codes, using an XML file is mandatory.
Adding triple-slash comments to an action enhances the Swagger UI by adding the description to the section header. Add a <summary>
element above the Delete
action:
/// <summary> /// Deletes a specific TodoItem. /// </summary> /// <param name="id"></param> /// <returns></returns> [HttpDelete("{id}")] public async Task<IActionResult> Delete(long id) { var item = await _context.TodoItems.FindAsync(id); if (item is null) { return NotFound(); } _context.TodoItems.Remove(item); await _context.SaveChangesAsync(); return NoContent(); }
The Swagger UI displays the inner text of the preceding code’s <summary>
element:

The UI is driven by the generated JSON schema:
"delete": { "tags": [ "Todo" ], "summary": "Deletes a specific TodoItem.", "parameters": [ { "name": "id", "in": "path", "description": "", "required": true, "schema": { "type": "integer", "format": "int64" } } ], "responses": { "200": { "description": "Success" } } },
To provide more detailed information in the Swagger UI, add a <remarks>
element to the Create action method documentation. This element supplements the information specified in the <summary>
element and makes the Swagger UI more comprehensive. You can add any relevant content in the <remarks>
element, such as text, JSON, or XML.
/// <summary> /// Creates a TodoItem. /// </summary> /// <param name="item"></param> /// <returns>A newly created TodoItem</returns> /// <remarks> /// Sample request: /// /// POST /Todo /// { /// "id": 1, /// "name": "Item #1", /// "isComplete": true /// } /// /// </remarks> /// <response code="201">Returns the newly created item</response> /// <response code="400">If the item is null</response> [HttpPost] [ProducesResponseType(StatusCodes.Status201Created)] [ProducesResponseType(StatusCodes.Status400BadRequest)] public async Task<IActionResult> Create(TodoItem item) { _context.TodoItems.Add(item); await _context.SaveChangesAsync(); return CreatedAtAction(nameof(Get), new { id = item.Id }, item); }
Notice the UI enhancements with these additional comments:

Data annotations for Swagger UI
Use attributes from the System.ComponentModel.DataAnnotations namespace to annotate the model and assist in driving the Swagger UI components.
Add the [Required]
attribute to the Name
property of the TodoItem
class:
using System.ComponentModel; using System.ComponentModel.DataAnnotations; namespace SwashbuckleSample.Models; public class TodoItem { public long Id { get; set; } [Required] public string Name { get; set; } = null!; [DefaultValue(false)] public bool IsComplete { get; set; } }
The presence of this attribute changes the UI behavior and alters the underlying JSON schema:
"schemas": { "TodoItem": { "required": [ "name" ], "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "name": { "type": "string" }, "isComplete": { "type": "boolean", "default": false } }, "additionalProperties": false } },
Add the [Produces("application/json")]
attribute to the API controller. Its purpose is to declare that the controller’s actions support a response content type of application/json:
[ApiController] [Route("api/[controller]")] [Produces("application/json")] public class TodoController : ControllerBase { }
The Media type drop-down selects this content type as the default for the controller’s GET actions:

By incorporating data annotations into your web API, you can enhance the usability of the API help pages and make the Swagger UI more descriptive and informative.
Describe response types
Developers consuming a web API are most concerned with what’s returned—specifically response types and error codes (if not standard). The response types and error codes are denoted in the XML comments and data annotations.
The Create
action returns an HTTP 201 status code on success. An HTTP 400 status code is returned when the posted request body is null. Without proper documentation in the Swagger UI, the consumer lacks knowledge of these expected outcomes. Fix that problem by adding the highlighted lines in the following example:
/// <summary> /// Creates a TodoItem. /// </summary> /// <param name="item"></param> /// <returns>A newly created TodoItem</returns> /// <remarks> /// Sample request: /// /// POST /Todo /// { /// "id": 1, /// "name": "Item #1", /// "isComplete": true /// } /// /// </remarks> /// <response code="201">Returns the newly created item</response> /// <response code="400">If the item is null</response> [HttpPost] [ProducesResponseType(StatusCodes.Status201Created)] [ProducesResponseType(StatusCodes.Status400BadRequest)] public async Task<IActionResult> Create(TodoItem item) { _context.TodoItems.Add(item); await _context.SaveChangesAsync(); return CreatedAtAction(nameof(Get), new { id = item.Id }, item); }
The Swagger UI now clearly documents the expected HTTP response codes:

Customize the Swagger UI
The default UI is both functional and presentable. However, API documentation pages should represent your brand or theme. To achieve this, you’ll need to add resources for serving static files and create a folder structure for hosting those files in order to brand the Swashbuckle components.
Enable Static File Middleware:
app.UseHttpsRedirection(); app.UseStaticFiles(); app.MapControllers();
To inject additional CSS stylesheets, add them to the project’s wwwroot folder and specify the relative path in the middleware options:
app.UseSwaggerUI(options => { options.InjectStylesheet("/swagger-ui/custom.css"); });
By adding the following CSS snippet, you can change the color of the Swagger UI header and customize the appearance of the GET
action:
/* Header */ .swagger-ui .topbar { background-color: #4338ca; } .swagger-ui .topbar .download-url-wrapper .select-label select { border: 2px solid #000; } /* GET Action */ .swagger-ui .opblock.opblock-get .opblock-summary { border-color: #4338ca; } .swagger-ui .opblock.opblock-get .opblock-summary-method { background: #4338ca; } .swagger-ui .opblock.opblock-get { background: #d9d6ff; border-color: #4338ca; }
After applying the branding colors to the Swagger UI header and other elements, you can see that the UI now reflects your organization’s brand identity.

Conclusion
To sum it up, implementing Swagger UI in an ASP.NET Core Web API can significantly enhance the development experience. Make it easier for users to consume your API. I’m confident that you now know how to add Swagger to Web API project.
With Swagger annotations and data annotations, you can ensure that your API is well-documented and easy to use. This can provide detailed descriptions of your API’s functionality and parameters. Which is easier for users to understand how to interact with your API.
By adding custom CSS styles to the Swagger UI, you can create a visually appealing UI that aligns with your brand identity. This can help establish brand recognition and create a more cohesive user experience. The [ProducesResponseType] can help streamline the process and reduce code redundancy.
Overall, incorporating Swagger into your ASP.NET Core Web API is a smart choice. As it can significantly improve the developer experience and simplify the process of consuming your API.
With the benefits outlined in this post, you can confidently add Swagger to your next project. Surly, You can enhance the API’s overall usability and functionality.
Thank you for reading, and happy coding!