API Versioning in .NET Web API

api-versioning-in.net-web-api

As your API evolves, breaking changes are inevitable. Introducing API versioning ensures that your clients continue to work without disruption while you introduce new features and improvements.

This guide covers how to implement API versioning in .NET Web API with practical examples, including a clean BaseApiController approach for centralized configuration.

Why API Versioning?

  • Backward Compatibility: Old clients continue to work with previous versions.
  • Smooth Upgrades: You can introduce new endpoints without breaking existing functionality.
  • Clear Communication: Clients know which version they are using.
  • Better Lifecycle Management: Easier to deprecate old versions gradually.

Step 1: Add Required NuGet Package

dotnet add package Microsoft.AspNetCore.Mvc.Versioning

This package provides tools to version your API by query string, header, or URL segment.

Step 2: Configure Versioning in Program.cs

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

// Add API versioning
builder.Services.AddApiVersioning(options =>
{
    options.AssumeDefaultVersionWhenUnspecified = true;
    options.DefaultApiVersion = new Microsoft.AspNetCore.Mvc.ApiVersion(1, 0);
    options.ReportApiVersions = true; // Returns API versions in response headers
});

var app = builder.Build();

app.MapControllers();
app.Run();

Step 3: Create a BaseApiController

A BaseApiController can hold common configuration, attributes, and helper methods for all versioned controllers.

using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
public abstract class BaseApiController : ControllerBase
{
    protected IActionResult ApiResponse(object data, int statusCode = 200)
    {
        return StatusCode(statusCode, new
        {
            Status = statusCode,
            Data = data,
            Version = HttpContext.GetRequestedApiVersion()?.ToString()
        });
    }
}

All your versioned controllers can now inherit from this base controller for consistent behavior.

Step 4: Versioning Controllers Using BaseApiController

[ApiVersion("1.0")]
public class ProductsController : BaseApiController
{
    [HttpGet]
    public IActionResult Get() => ApiResponse(new[] { "Product 1", "Product 2" });
}

[ApiVersion("2.0")]
public class ProductsV2Controller : BaseApiController
{
    [HttpGet]
    public IActionResult Get() => ApiResponse(new[] { "Product A", "Product B", "Product C" });
}

This keeps your code DRY and centralizes versioning logic.

Step 5: Query String and Header-Based Versioning

Query string example:

GET /api/orders?api-version=1.0
GET /api/orders?api-version=2.0

Header-based configuration in Program.cs:

builder.Services.AddApiVersioning(options =>
{
    options.AssumeDefaultVersionWhenUnspecified = true;
    options.DefaultApiVersion = new ApiVersion(1, 0);
    options.ApiVersionReader = new HeaderApiVersionReader("x-api-version");
    options.ReportApiVersions = true;
});

Clients can now set the header:

x-api-version: 2.0

Step 6: Deprecating Versions

[ApiVersion("1.0", Deprecated = true)]
public class OldController : BaseApiController
{
    [HttpGet]
    public IActionResult Get() => ApiResponse("This version is deprecated");
}

Headers will indicate deprecation.

Step 7: Swagger Integration for Versioned APIs

builder.Services.AddSwaggerGen(options =>
{
    options.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "API v1", Version = "v1" });
    options.SwaggerDoc("v2", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "API v2", Version = "v2" });
});

var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI(options =>
{
    options.SwaggerEndpoint("https://dev.to/swagger/v1/swagger.json", "API v1");
    options.SwaggerEndpoint("https://dev.to/swagger/v2/swagger.json", "API v2");
});

Wrapping Up

Using a BaseApiController centralizes common logic, keeps controllers DRY, and makes managing API versioning cleaner. Combined with URL, query string, or header-based versioning and Swagger integration, this approach provides a flexible and maintainable API structure in .NET.

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post
september-2025-gaps-progress-report-released-by-america-makes-and-ansi-additive-manufacturing-standards-collaborative

September 2025 Gaps Progress Report Released by America Makes and ANSI Additive Manufacturing Standards Collaborative

Next Post
deploying-vanity-urls-for-oracle-apex-on-oci

Deploying Vanity URLs for Oracle APEX on OCI

Related Posts