codewithmukesh/dotnet-claude-kit

api-versioning

API versioning strategies for ASP.NET Core.

View source
Original skill document

Rendered from the source repository. Headings, examples, code, tables, links, and referenced images are preserved.

API Versioning

Core Principles

  1. Version from day one — Adding versioning later is painful. Start with a version in the URL even if you only have v1.
  2. URL segment versioning is the default/api/v1/orders is the most discoverable and cache-friendly strategy.
  3. Never break existing versions — Add a new version for breaking changes. Deprecate the old version with a timeline.
  4. Version the API, not individual endpoints — All endpoints in a version group share the same version number.

Patterns

Setup with Asp.Versioning

csharp
// Program.cs
builder.Services.AddApiVersioning(options =>
{
    options.DefaultApiVersion = new ApiVersion(1, 0);
    options.AssumeDefaultVersionWhenUnspecified = true;
    options.ReportApiVersions = true;
    options.ApiVersionReader = new UrlSegmentApiVersionReader();
})
.AddApiExplorer(options =>
{
    options.GroupNameFormat = "'v'VVV";
    options.SubstituteApiVersionInUrl = true;
});

URL Segment Versioning (Recommended)

csharp
var v1 = app.NewApiVersionSet()
    .HasApiVersion(new ApiVersion(1, 0))
    .Build();

var v2 = app.NewApiVersionSet()
    .HasApiVersion(new ApiVersion(2, 0))
    .Build();

app.MapGroup("/api/v{version:apiVersion}/orders")
    .WithApiVersionSet(v1)
    .WithTags("Orders")
    .MapOrderEndpointsV1();

app.MapGroup("/api/v{version:apiVersion}/orders")
    .WithApiVersionSet(v2)
    .WithTags("Orders")
    .MapOrderEndpointsV2();

Header Versioning (Alternative)

csharp
options.ApiVersionReader = new HeaderApiVersionReader("X-Api-Version");

// Client sends: X-Api-Version: 2.0

Deprecating a Version

csharp
var v1 = app.NewApiVersionSet()
    .HasDeprecatedApiVersion(new ApiVersion(1, 0))
    .HasApiVersion(new ApiVersion(2, 0))
    .Build();

// Response headers will include: api-deprecated-versions: 1.0

Version-Specific Endpoint Groups

csharp
public static class OrderEndpointsV1
{
    public static RouteGroupBuilder MapOrderEndpointsV1(this RouteGroupBuilder group)
    {
        group.MapGet("/{id:guid}", GetOrderV1);
        group.MapPost("/", CreateOrderV1);
        return group;
    }

    private static async Task<Results<Ok<OrderResponseV1>, NotFound>> GetOrderV1(
        Guid id, ISender sender, CancellationToken ct)
    {
        // V1 response shape
        var result = await sender.Send(new GetOrder.Query(id), ct);
        return result.IsSuccess
            ? TypedResults.Ok(result.Value.ToV1())
            : TypedResults.NotFound();
    }
}

public static class OrderEndpointsV2
{
    public static RouteGroupBuilder MapOrderEndpointsV2(this RouteGroupBuilder group)
    {
        group.MapGet("/{id:guid}", GetOrderV2);
        group.MapPost("/", CreateOrderV2);
        return group;
    }

    private static async Task<Results<Ok<OrderResponseV2>, NotFound>> GetOrderV2(
        Guid id, ISender sender, CancellationToken ct)
    {
        // V2 response shape — includes new fields
        var result = await sender.Send(new GetOrder.Query(id), ct);
        return result.IsSuccess
            ? TypedResults.Ok(result.Value.ToV2())
            : TypedResults.NotFound();
    }
}

Anti-patterns

Don't Version Individual Endpoints

csharp
// BAD — inconsistent versioning within a group
app.MapGet("/api/v1/orders", ListOrdersV1);
app.MapGet("/api/v2/orders/{id}", GetOrderV2); // V2 only for this endpoint?

// GOOD — version the entire group
app.MapGroup("/api/v1/orders").MapOrderEndpointsV1();
app.MapGroup("/api/v2/orders").MapOrderEndpointsV2();

Don't Use Query String Versioning as Default

csharp
// BAD for REST APIs — version hidden in query string, not cache-friendly
GET /api/orders?api-version=2.0

// GOOD — version in URL, discoverable and cacheable
GET /api/v2/orders

Decision Guide

ScenarioRecommendation
New public APIURL segment versioning from day one
Internal API between servicesHeader versioning (cleaner URLs)
Breaking response shape changeNew version
Adding new optional fieldsSame version (backwards compatible)
Deprecating a versionMark deprecated, set sunset date, document migration path
from this repository

More skills

All skills
codewithmukesh
Community

arch-check

Architecture conformance check: verifies an existing codebase against its declared architecture (VSA, Clean Architecture, DDD, Modular Monolith) — dependency direction, layer violations, module boundary leaks, and cycles — using token-cheap Roslyn MCP analysis. Invoke when: "check architecture", "architecture violations", "layer violations", "dependency direction", "module boundaries", "arch check", "is my architecture clean", "enforce architecture", "conformance check". For CHOOSING an architecture, use architecture-advisor instead.

installs
2
GitHub stars
692
Updated
Aug 7
codewithmukesh
Community

architecture-advisor

Architecture selection advisor for .NET applications. Asks structured questions about domain complexity, team size, system lifetime, compliance, and integration needs, then recommends the best-fit architecture: Vertical Slice, Clean Architecture, DDD + Clean Architecture, or Modular Monolith. Load this skill when the user asks "which architecture", "choose architecture", "set up project", "new project", "architecture decision", "restructure", or "how should I organize". Always load BEFORE any architecture-specific skill.

installs
2
GitHub stars
692
Updated
Aug 7
codewithmukesh
Community

aspire

.NET Aspire for cloud-native orchestration. Covers AppHost configuration, service defaults, resource configuration, service discovery, and the Aspire dashboard. Load this skill when setting up local development orchestration, service discovery, or Aspire-managed infrastructure, or when the user mentions "Aspire", "AppHost", "service defaults", "service discovery", "orchestration", "Aspire dashboard", "AddProject", "WithReference", or "cloud-native .NET".

installs
2
GitHub stars
692
Updated
Aug 7
codewithmukesh
Community

authentication

Authentication and authorization for ASP.NET Core. Covers JWT bearer tokens, OpenID Connect, ASP.NET Identity, authorization policies, role and claim-based authorization, and API key authentication. Load this skill when implementing login, protecting endpoints, designing authorization rules, or when the user mentions "auth", "JWT", "bearer token", "OIDC", "OpenID Connect", "Identity", "claims", "roles", "authorize", "RequireAuthorization", "API key", or "cookie auth".

installs
2
GitHub stars
692
Updated
Aug 7