Swagger UI provides a browser-based interface for exploring and testing your Web API — every endpoint is documented with request parameters, request body schema, response types, and status codes. It is generated automatically from your code using the OpenAPI specification. For developers building the Angular frontend in Part 5, Swagger is the living API contract: they see exactly which endpoints exist, what they expect, and what they return without reading source code. In production, Swagger should be disabled or secured — it exposes your full API surface.
Configuring Swagger
// dotnet add package Swashbuckle.AspNetCore
// ── Program.cs — Swagger configuration ───────────────────────────────────
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(opts =>
{
opts.SwaggerDoc("v1", new OpenApiInfo
{
Title = "BlogApp API",
Version = "v1",
Description = "REST API for BlogApp — posts, comments, users.",
Contact = new OpenApiContact { Name = "BlogApp Team", Email = "api@blogapp.com" },
});
// Include XML documentation comments in Swagger
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
if (File.Exists(xmlPath))
opts.IncludeXmlComments(xmlPath);
// Add JWT Bearer security definition
opts.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT",
Description = "Enter JWT token (without 'Bearer' prefix)",
});
opts.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer",
}
},
Array.Empty<string>()
}
});
});
// ── Middleware — only in Development ──────────────────────────────────────
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(opts =>
{
opts.SwaggerEndpoint("/swagger/v1/swagger.json", "BlogApp API v1");
opts.RoutePrefix = string.Empty; // serve at app root /
opts.PersistAuthorization = true; // remember JWT token across refreshes
});
}
.csproj file: <GenerateDocumentationFile>true</GenerateDocumentationFile> and suppress the missing-comment warning with <NoWarn>$(NoWarn);1591</NoWarn> (1591 = “missing XML comment for publicly visible type or member”). XML comments on controller actions appear in Swagger as endpoint descriptions. Use /// <summary>Get a post by ID</summary> on the action and /// <param name="id">The post ID</param> for parameters. This is the most impactful documentation you can write for API consumers.nswag openapi2tsclient /input:swagger.json /output:src/app/api/client.ts to generate a strongly-typed Angular HTTP client. The generated client handles serialisation, error handling, and URL building automatically. This eliminates an entire category of Angular-API integration bugs: mismatched property names, wrong endpoint URLs, and unhandled error shapes.if (app.Environment.IsDevelopment())) already shown above.XML Documentation Comments
/// <summary>
/// Retrieves a paginated list of published posts.
/// </summary>
/// <param name="page">Page number (1-based). Default: 1.</param>
/// <param name="size">Number of posts per page (1-100). Default: 10.</param>
/// <returns>A paginated list of post summaries.</returns>
/// <response code="200">Returns the paginated post list.</response>
/// <response code="400">Invalid pagination parameters.</response>
[HttpGet]
[ProducesResponseType(typeof(PagedResult<PostSummaryDto>), 200)]
[ProducesResponseType(typeof(ValidationProblemDetails), 400)]
public async Task<ActionResult<PagedResult<PostSummaryDto>>> GetAll(
[FromQuery] int page = 1,
[FromQuery][Range(1, 100)] int size = 10,
CancellationToken ct = default)
{
var result = await _service.GetPageAsync(page, size, ct);
return Ok(result);
}
Common Mistakes
Mistake 1 — Enabling Swagger in production (exposes API surface to attackers)
❌ Wrong — UseSwagger() called unconditionally; production API fully documented for attackers.
✅ Correct — wrap in if (app.Environment.IsDevelopment()) or secure with authentication in staging.
Mistake 2 — Not adding [ProducesResponseType] attributes (inaccurate Swagger documentation)
❌ Wrong — Swagger only documents 200 responses; clients unaware of 404, 400, 401 possibilities.
✅ Correct — add [ProducesResponseType] for every possible status code the action can return.