API Versioning in C# .NET Core

By FoxLearn 1/10/2025 7:20:27 AM   23
In .NET Core, managing API versions is a critical aspect of maintaining backward compatibility and evolving your APIs without breaking existing clients.

This article walks through the process of setting up API versioning using the Microsoft.AspNetCore.Mvc.Versioning NuGet package.

Implementing API Versioning in C# .NET Core with Microsoft.AspNetCore.Mvc.Versioning

1. Create a Controller

First, let's create a simple controller and add versioning to the route. You will define a version in the route using a custom template.

using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;

namespace Controllers.V1
{
    [Route("v{version:apiVersion}/[controller]")]
    public class HelloWorldController : Controller
    {
        [HttpGet]
        public async Task<IActionResult> HelloWorld()
        {
            // A simple async response as an example.
            return await Task.Run(() => Ok("Hello world"));
        }
    }
}

In the [Route] attribute, notice how the version is included in the route as v{version:apiVersion}/[controller]. The {version:apiVersion} placeholder tells the framework to expect an API version as part of the URL.

2. Configure API Versioning in Services

Next, configure API versioning in the Startup.cs (or Program.cs for .NET 6 and above). This tells the application to use API versioning and associates specific versions with controllers.

using Microsoft.AspNetCore.Mvc.Versioning;
using Microsoft.AspNetCore.Mvc;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddApiVersioning(options =>
        {
            options.ReportApiVersions = true;  // Enable reporting of API versions
            options.Conventions.Controller<Controllers.V1.HelloWorldController>()
                   .HasApiVersion(new ApiVersion(1, 0));  // Assign version 1.0 to the controller
        });

        // Other services...
    }
}

Here, we use AddApiVersioning() to set up versioning. The HasApiVersion method links the HelloWorldController to version 1.0 of the API.

3. Access Your Versioned Endpoint

Once the versioning is set up, you can access the endpoint by specifying the version in the URL:

/v1/helloworld

You might wonder, "Why not just hardcode the version directly into the route?" While that approach can work, API versioning provides greater flexibility and benefits:

  1. Deprecation Support: Easily mark versions as deprecated without breaking changes.
  2. Multiple Versions per Controller: A single controller can handle multiple versions of the same endpoint.
  3. Granular Version Control: You can manage the versioning of individual methods, providing a finer level of control.

For example, to deprecate a version, you can use the ApiVersion attribute on the controller:

[Route("v{version:apiVersion}/[controller]")]
[ApiVersion("1.0", Deprecated = true)]
public class HelloWorldController : Controller
{
    [HttpGet]
    public async Task<IActionResult> HelloWorld()
    {
        return await Task.Run(() => Ok("Hello world"));
    }
}

Additionally, if you want different versions for methods within the same controller, use the MapToApiVersion attribute:

[HttpGet]
[MapToApiVersion("1.0")]
public async Task<IActionResult> HelloWorld()
{
    return await Task.Run(() => Ok("Hello from version 1.0"));
}

API versioning in C# .NET Core offers several advantages over hardcoding versioning directly into routes.

By using the Microsoft.AspNetCore.Mvc.Versioning package, you can handle API evolution smoothly, deprecate older versions, and manage multiple versions in a single controller. Though .NET 6 Minimal APIs don’t support versioning out-of-the-box yet, future updates may provide this feature, so keep an eye on upcoming releases.