The most surprising thing about Swagger/OpenAPI integration with .NET is how little code you actually need to write to get a fully functional API documentation and testing interface.

Let’s see it in action. Imagine you have a simple ASP.NET Core Web API project.

// Controllers/WeatherForecastController.cs
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;

namespace SwaggerDotNetIntegration.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };

        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }
}
// Models/WeatherForecast.cs
using System;

namespace SwaggerDotNetIntegration.Models
{
    public class WeatherForecast
    {
        public DateTime Date { get; set; }
        public int TemperatureC { get; set; }
        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
        public string Summary { get; set; }
    }
}

That’s it for the application code. Now, let’s add Swashbuckle, the most popular OpenAPI/Swagger tool for .NET.

First, add the necessary NuGet packages to your project. You’ll typically need Swashbuckle.AspNetCore.

dotnet add package Swashbuckle.AspNetCore

Next, configure Swashbuckle in your Startup.cs (or Program.cs for newer .NET versions).

In Startup.cs (for .NET Core 3.1 and earlier):

// Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models; // Add this namespace

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        // Register the Swagger generator, defining 1 or more Swagger documents
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
        });
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });

        // Enable middleware to serve generated Swagger as a JSON endpoint.
        app.UseSwagger();

        // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
        // specifying the Swagger JSON endpoint.
        app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"));
    }
}

In Program.cs (for .NET 6 and later):

// Program.cs
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "My API", Version = "v1" });
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

With these changes, when you run your application and navigate to /swagger (e.g., https://localhost:5001/swagger), you’ll see the Swagger UI. This UI automatically discovers your API endpoints, models, and parameters based on your controllers and C# types. You can even test your endpoints directly from the UI by clicking the "Try it out" button.

The core problem Swashbuckle solves is bridging the gap between your C# code and the standardized OpenAPI specification. It does this by inspecting your compiled application at runtime. It uses reflection to discover controllers, action methods, route templates, HTTP verb attributes ([HttpGet], [HttpPost]), parameter types, and return types. It then translates this information into the JSON or YAML format required by the OpenAPI specification. The AddSwaggerGen call configures the generator, and UseSwagger and UseSwaggerUI configure the middleware to serve the generated JSON and render the interactive UI.

The exact levers you control are primarily within the AddSwaggerGen configuration lambda. You can customize the OpenApiInfo with details like description, terms of service, and contact information. You can also add XML comments to your C# code, and Swashbuckle can be configured to read these comments and include descriptions, parameter details, and example values directly in your Swagger documentation.

To enable XML comments:

  1. In your project file (.csproj), add <GenerateDocumentationFile>true</GenerateDocumentationFile> within the <PropertyGroup>.
  2. In Startup.cs or Program.cs, within the AddSwaggerGen configuration, add:
    c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"));
    

For example, adding a comment to your controller action:

/// <summary>
/// Gets a list of weather forecasts.
/// </summary>
/// <returns>A collection of weather forecast objects.</returns>
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
    // ... implementation
}

This will result in the Swagger UI displaying the "Gets a list of weather forecasts." description and showing the WeatherForecast object structure with its properties.

The next concept you’ll likely explore is customizing the schema generation, particularly for handling complex types, enums, or adding specific examples and constraints that aren’t directly inferable from the C# code alone.

Want structured learning?

Take the full Swagger course →