// v1: returns { name: string }
// v2: returns { firstName: string, lastName: string }
// Both versions coexist so old clients keep working during a migration window
Topics
31
.NET CLI, SDK & Project Structure (csproj)
.NET vs .NET Framework
API Versioning
ASP.NET Core Middleware & Request Pipeline
Assemblies & NuGet
Authentication & Authorization (Identity, JWT, OAuth)
Background Services
Blazor (Server & WebAssembly)
Caching (In-Memory, Distributed & Redis)
CI/CD, Publishing & Deployment
CLR & Runtime
Configuration & Options
CORS & Cross-Origin Resource Sharing
Dependency Injection
Diagnostics & Performance
Docker & Containerization
Entity Framework Core & Data Access
Generic Host
Global Exception Handling & Middleware
gRPC Services
Health Checks & Readiness/Liveness Probes
Logging
Microservices & Distributed Architecture Patterns
Minimal APIs
MVC & Razor Pages
Rate Limiting & Throttling
RESTful Web APIs & Controllers
Secrets Management & Configuration Providers (Key Vault, User Secrets)
SignalR & Real-Time Communication
Testing in .NET (xUnit, Integration & Unit Testing)
Worker Services & IHostedService
API Versioning
15 questions found
API versioning lets you evolve an API's contract (adding fields, changing behavior, removing deprecated endpoints) without breaking existing clients that depend on the current behavior. Without versioning, any breaking change forces every consumer to update simultaneously, which is impractical for public APIs or APIs with many independent client teams.
Real-world example
A payments API maintains v1 and v2 simultaneously for six months after a breaking schema change, giving integrator partners time to migrate before v1 is eventually deprecated and removed.
RESTful Web APIs & Controllers;CI/CD
Publishing & Deployment
What are the main strategies for versioning an ASP.NET Core API (URL, query string, header, media type)?
IntermediateURL segment versioning (/api/v1/products) is the most visible and cache-friendly approach. Query string versioning (/api/products?api-version=1.0) keeps URLs stable but is less discoverable. Header versioning (a custom header like X-Api-Version) keeps URLs completely clean but is less visible in browsers/docs. Media type versioning (Accept: application/json;v=1.0) follows REST/HATEOAS purism but is the least commonly adopted in practice.
// URL segment (most common)
[Route("api/v{version:apiVersion}/products")]
// Query string
// GET /api/products?api-version=1.0
// Header
// GET /api/products Header: X-Api-Version: 1.0
Real-world example
A public-facing API chooses URL segment versioning (/api/v2/orders) specifically because it's the most discoverable and cache-proxy-friendly option for third-party integrators reading documentation.
RESTful Web APIs & Controllers;ASP.NET Core Middleware & Request Pipeline
How do you implement URL-based API versioning using the Asp.Versioning.Mvc package in ASP.NET Core?
IntermediateThe Asp.Versioning packages (successor to Microsoft.AspNetCore.Mvc.Versioning) let you register API versioning services, define supported versions per controller/action via [ApiVersion] attributes, and use a {version:apiVersion} route template placeholder so the framework automatically routes requests to the correct versioned controller or action.
builder.Services.AddApiVersioning(options => {
options.DefaultApiVersion = new ApiVersion(1, 0);
options.AssumeDefaultVersionWhenUnspecified = true;
});
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/products")]
public class ProductsV1Controller : ControllerBase { }
[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/products")]
public class ProductsV2Controller : ControllerBase { }
Real-world example
An e-commerce API adds a ProductsV2Controller alongside the existing V1 controller when the product schema needs a breaking change, letting both versions run simultaneously in production.
ASP.NET Core Middleware & Request Pipeline;RESTful Web APIs & Controllers
How can you version a single controller action to support multiple API versions without duplicating the entire controller class?
AdvancedInstead of separate controller classes per version, you can apply multiple [ApiVersion] attributes to one controller and use [MapToApiVersion("x.0")] on individual actions to indicate which specific version(s) an action supports, letting you share common actions across versions while only duplicating the ones that actually changed.
[ApiVersion("1.0")]
[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/products")]
public class ProductsController : ControllerBase {
[HttpGet]
public IActionResult GetAll() => Ok(_products); // shared across both versions
[HttpGet("{id}")]
[MapToApiVersion("2.0")]
public IActionResult GetByIdV2(int id) => Ok(_v2Format); // only in v2
}
Real-world example
An API adds a new filtering capability only in v2's GetAll action while keeping the v1 GetById action completely shared, minimizing duplicated code across versions within one controller.
RESTful Web APIs & Controllers;ASP.NET Core Middleware & Request Pipeline
The Asp.Versioning library can automatically add an `api-supported-versions` header (listing currently supported versions) and an `api-deprecated-versions` header (listing versions still functional but scheduled for removal) to every response, giving clients a machine-readable way to detect upcoming breaking changes proactively rather than being surprised when a version is finally removed.
builder.Services.AddApiVersioning(options => {
options.ReportApiVersions = true; // adds api-supported-versions / api-deprecated-versions headers
});
[ApiVersion("1.0", Deprecated = true)]
[ApiVersion("2.0")]
public class ProductsController : ControllerBase { }
Real-world example
A partner integration team writes automated monitoring that checks the api-deprecated-versions header on every API response, automatically filing a ticket when their integration is still using a version flagged as deprecated.
RESTful Web APIs & Controllers;Diagnostics & Performance
What's the difference between versioning a REST API's contract versus versioning its underlying data model, and why does that distinction matter?
AdvancedAPI contract versioning concerns the shape of requests/responses exposed to clients (JSON structure, field names, endpoint paths), while the underlying data model (database schema, internal domain objects) can evolve independently as long as a translation/mapping layer (like DTOs) adapts between the internal model and each exposed API version's contract -- letting you refactor internals freely without forcing a new API version for every internal change.
// Internal domain model can change freely
public class ProductEntity { public decimal Price { get; set; } public string Currency { get; set; } }
// v1 DTO stays stable regardless of internal changes
public class ProductV1Dto { public decimal Price { get; set; } } // USD assumed
// v2 DTO exposes the new capability
public class ProductV2Dto { public decimal Amount { get; set; } public string Currency { get; set; } }
Real-world example
A team refactors their internal Product entity extensively to support multi-currency pricing without bumping the API version at all, since a mapping layer keeps translating to the unchanged v1 DTO shape for existing clients.
Entity Framework Core & Data Access;RESTful Web APIs & Controllers
How does semantic versioning (SemVer) inform decisions about when to bump an API's major, minor, or patch version?
IntermediateSemantic versioning conventions (MAJOR.MINOR.PATCH) map naturally to API changes: a MAJOR bump signals breaking changes (removed fields, changed response shapes, incompatible behavior), a MINOR bump signals backward-compatible additions (new optional fields, new endpoints), and a PATCH bump signals backward-compatible bug fixes with no contract change. Most public API versioning schemes (like /api/v1, /api/v2) only expose the MAJOR component externally, treating MINOR/PATCH as internal implementation detail that doesn't require client action.
// Externally exposed: only major version
// /api/v1/products /api/v2/products
// Internally tracked via SemVer in release notes:
// v1.3.2 -- patch fix, no client action needed
// v1.4.0 -- new optional field added, backward compatible
// v2.0.0 -- breaking change, new URL segment required
Real-world example
An API's changelog documents every release using full SemVer internally (v1.4.2, v1.5.0) while only the major version (v1, v2) is ever reflected in the actual URL path clients call, keeping the versioning surface simple for consumers.
RESTful Web APIs & Controllers;CI/CD
Publishing & Deployment
What is the 'tolerant reader' pattern, and how does it reduce the need for frequent API versioning?
AdvancedThe tolerant reader pattern designs API clients to ignore unknown fields and gracefully handle missing optional fields, rather than strictly validating against an exact expected schema. When both server and client follow this principle, many additive, backward-compatible changes (new optional fields, extra response properties) don't require a version bump at all, since well-behaved clients simply ignore what they don't understand.
// Server adds a new optional field without a version bump:
{ "id": 1, "name": "Widget", "weightKg": 2.5 } // new field
// Tolerant client (e.g., using JsonSerializerOptions with unmapped members ignored)
var options = new JsonSerializerOptions {
UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip
};
Real-world example
A mobile app built with a tolerant JSON deserializer continues working seamlessly when the backend team adds new optional fields to API responses, avoiding an app-store release cycle just to accommodate additive backend changes.
RESTful Web APIs & Controllers;Global Exception Handling & Middleware
How do you version an API's OpenAPI/Swagger documentation to show separate docs per version?
IntermediateUsing Swashbuckle or NSwag together with the versioning library's IApiVersionDescriptionProvider, you can generate a separate OpenAPI document per registered API version, configuring Swagger UI to expose a dropdown letting consumers switch between documented versions (e.g., /swagger/v1/swagger.json and /swagger/v2/swagger.json).
builder.Services.AddSwaggerGen();
builder.Services.ConfigureOptions<ConfigureSwaggerOptions>();
app.UseSwaggerUI(options => {
foreach (var description in provider.ApiVersionDescriptions)
options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
});
Real-world example
An API's public developer portal shows a version dropdown in Swagger UI, letting third-party integrators explore both the current v2 and the still-supported legacy v1 documentation side by side.
ASP.NET Core Middleware & Request Pipeline;RESTful Web APIs & Controllers
What are the trade-offs of versioning an entire API at once (global versioning) versus versioning individual endpoints independently?
AdvancedGlobal versioning (bump the whole API to v2 even if only one endpoint changed) is simpler to reason about and communicate but forces clients to migrate everything at once, even unaffected endpoints. Independent endpoint versioning (only the changed endpoint gets a new version while others stay stable) minimizes unnecessary client churn but increases complexity in routing, documentation, and mental overhead of tracking which specific endpoints are at which version.
// Global versioning: entire API bumps together
// /api/v2/products /api/v2/orders /api/v2/customers (all v2, even if only products changed)
// Independent versioning: only the changed resource bumps
// /api/v1/orders /api/v2/products /api/v1/customers (mixed versions)
Real-world example
A large platform API with dozens of resource types adopts independent endpoint versioning specifically to avoid forcing every integrator to re-test their entire integration whenever any single unrelated endpoint changes.
RESTful Web APIs & Controllers;Microservices & Distributed Architecture Patterns
Showing 1–10 of 15