GB.
2025-06-076 min read

API Versioning in ASP.NET Core

#API Versioning#ASP.NET Core#Web API#.NET#Best Practices

API Versioning in ASP.NET Core

If you are building public APIs that evolve over time, you will eventually face the challenge of changing endpoints without breaking existing clients. API versioning helps you introduce new features while keeping old versions stable.

You probably have these questions:

  • How do I version my APIs without duplicating too much code?
  • Which versioning strategy is best - URL, Query String, Header, or Media Type?
  • How do I deprecate old versions gracefully?

Let's break it down clearly with practical examples.

Why API Versioning Matters

Without proper versioning, any change to your API (new fields, changed behavior, or removed endpoints) can break client applications. Versioning allows you to:

  • Add new features safely
  • Fix bugs in newer versions
  • Deprecate old versions over time
  • Maintain backward compatibility

Versioning Strategies in ASP.NET Core

ASP.NET Core provides flexible ways to version your APIs. Here is a comparison:

StrategyExample URL / RequestProsCons
URL Path/api/v1/usersClear and visibleChanges URL structure
Query String/api/users?api-version=1.0No URL changeLess RESTful
HeaderX-API-Version: 1.0Clean URLsNot visible in URL
Media TypeAccept: application/json;v=1.0Most RESTfulComplex for clients

Most teams prefer URL Path versioning because it is explicit and easy to understand.

Implementing API Versioning

First, add the required package and configure services:

builder.Services.AddApiVersioning(options =>
{
    options.DefaultApiVersion = new ApiVersion(1, 0);
    options.AssumeDefaultVersionWhenUnspecified = true;
    options.ReportApiVersions = true;
    options.ApiVersionReader = new UrlSegmentApiVersionReader();
});

builder.Services.AddVersionedApiExplorer(options =>
{
    options.GroupNameFormat = "'v'VVV";
    options.SubstituteApiVersionInUrl = true;
});

Then decorate your controllers:

[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("1.0")]
public class UsersController : ControllerBase
{
    [HttpGet]
    public IActionResult GetUsersV1() { ... }
}

[ApiVersion("2.0")]
public class UsersController : ControllerBase
{
    [HttpGet]
    public IActionResult GetUsersV2() { ... }
}

You can also mark a version as deprecated:

[ApiVersion("1.0", Deprecated = true)]

Common Misconceptions About API Versioning

  • Myth: "Versioning means I have to duplicate all my code."
    Reality: Use inheritance, shared services, or separate controllers only for major changes.

  • Myth: "I should version every small change."
    Reality: Version only when you introduce breaking changes. Minor updates can stay in the same version.

  • Myth: "Query string versioning is the easiest."
    Reality: URL path versioning is usually cleaner for public APIs.

  • Myth: "Once I version an API, I can never remove it."
    Reality: You can deprecate versions and announce sunset dates.

Pro Tips from Real-World Projects

  • Use URL path versioning for public APIs and Header versioning for internal services.
  • Always include version information in responses using ReportApiVersions.
  • Document each version clearly using Swagger/OpenAPI with versioned endpoints.
  • Plan a deprecation policy and communicate it to clients well in advance.
  • Keep controllers thin and move common logic to shared services or base classes.
  • Test all active versions regularly to catch breaking changes early.

Final Summary - What You Should Remember

  • API versioning allows you to evolve your APIs without breaking existing clients
  • URL path versioning is the most popular and explicit strategy in ASP.NET Core
  • Use the built-in ApiVersioning package for clean implementation
  • Deprecate old versions gracefully instead of removing them suddenly
  • Combine versioning with good documentation and clear communication

Happy coding, and may your API versions always stay compatible and easy to maintain.

Enjoyed this article? Share it with your network!