Codebelt

Codebelt.Extensions.Asp.Versioning

RESTful Asp.Versioning extensions for Accept-header versioning and consistent error responses.

.NET 10.0 / .NET 9.0 MIT v10.0.8 5,883 downloads

Overview

Codebelt.Extensions.Asp.Versioning packages the repository's REST-oriented versioning behavior for ASP.NET Core APIs. Its main job is to register Asp.Versioning with a media-type parameter reader, align ApiExplorer output with the same parameter name, and shape versioning failures into exceptions or problem-details responses that the rest of the pipeline can handle consistently.

The package stays focused on that integration layer. It does not replace Asp.Versioning itself, but adds the reader, options, and middleware needed when version negotiation happens through the Accept header and the surrounding pipeline needs predictable error handling.

Key APIs

AddRestfulApiVersioning is the main entry point. It wires AddApiVersioning, MVC integration, and ApiExplorer registration together, then applies the package-specific defaults for AssumeDefaultVersionWhenUnspecified, the custom API version reader, explorer group names, and problem-details behavior.

RestfulApiVersioningOptions collects the knobs that drive that registration. The type exposes the default API version, reporting flag, convention builder, media-type parameter name, accepted media types, and the UseBuiltInRfc7807 switch that decides whether the package keeps ASP.NET Core's built-in RFC 7807 output or translates errors into Cuemon HTTP exceptions.

UseApiVersionSelector<T>() is the package's shortcut for swapping the IApiVersionSelector implementation without setting the selector type manually. The method stores the concrete selector type that AddRestfulApiVersioning later instantiates for Asp.Versioning.

RestfulApiVersionReader extends MediaTypeApiVersionReader with an allow-list for Accept headers. Its constructor takes the accepted media types and parameter name, and the overridden header-reading logic only forwards matching media types to the underlying Asp.Versioning reader.

UseRestfulApiVersioning adds request-pipeline behavior for status codes that were written directly to the response. By default it maps known status codes to HttpStatusCodeException instances and falls back to InternalServerErrorException for unmapped codes, but callers can provide their own factory when they need different exception translation.

Basic usage

using Asp.Versioning;
using Asp.Versioning.ApiExplorer;
using Codebelt.Extensions.Asp.Versioning;
using Codebelt.Extensions.Xunit;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Xunit;

namespace MyProject.Tests;

public class RestfulApiVersioningExample : Test
{
    public RestfulApiVersioningExample(ITestOutputHelper output) : base(output)
    {
    }

    [Fact]
    public void AddRestfulApiVersioning_ConfiguresRestfulExplorerAndReaderDefaults()
    {
        var services = new ServiceCollection();

        services.AddRestfulApiVersioning(options =>
        {
            options.ParameterName = "version";
            options.DefaultApiVersion = new ApiVersion(2, 0);
            options.UseApiVersionSelector<LowestImplementedApiVersionSelector>();
        });

        using var provider = services.BuildServiceProvider();
        var apiVersioning = provider.GetRequiredService<IOptions<ApiVersioningOptions>>().Value;
        var apiExplorer = provider.GetRequiredService<IOptions<ApiExplorerOptions>>().Value;
        var reader = Assert.IsType<RestfulApiVersionReader>(apiVersioning.ApiVersionReader);

        TestOutput.WriteLine($"Group name format: {apiExplorer.GroupNameFormat}");
        TestOutput.WriteLine($"Accepted media types: {string.Join(", ", reader.ValidAcceptHeaders)}");

        Assert.Equal(new ApiVersion(2, 0), apiExplorer.DefaultApiVersion);
        Assert.Equal("'version'VVV", apiExplorer.GroupNameFormat);
        Assert.True(apiExplorer.SubstituteApiVersionInUrl);
        Assert.Contains("application/json", reader.ValidAcceptHeaders);
    }
}

Use this pattern when one registration call should establish both your media-type version reader and the explorer metadata that OpenAPI tooling will consume. It matters because the same options object drives version selection, accepted media types, and explorer naming instead of forcing those decisions to drift across separate setup calls.

Installation

dotnet add package Codebelt.Extensions.Asp.Versioning

Usage guidance

Use this package when your API exposes versions through a media-type parameter on the Accept header and you want Asp.Versioning, ApiExplorer, and response shaping configured as one REST-oriented unit. If your API uses another versioning strategy, or if the plain Asp.Versioning defaults already fit your pipeline and error model, configure Asp.Versioning directly instead of adding this package-specific layer.