# ASP.NET API Versioning: Adding Version Semantics to Minimal APIs, MVC, gRPC and OData

> The Asp project adds versioning metadata and conventions to ASP.NET services without changing how you write them. Here is how the packages fit together, what a first setup looks like, and where the design forces you to make decisions.

**dotnet/aspnet-api-versioning** — Provides a set of libraries which add service API versioning to ASP.NET Core Minimal APIs, Controllers, gRPC, OData, and Web API (Classic).

- Repository: https://github.com/dotnet/aspnet-api-versioning
- Stars: 3,205 · Forks: 721
- Language: C#
- License: MIT
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/dotnet-aspnet-api-versioning

## What ASP.NET API Versioning actually solves

A REST service that lives long enough will need a second version. The usual approach is to bolt version segments onto routes by hand, duplicate controllers, and hope the two copies do not drift. ASP.NET API Versioning replaces that with metadata: you describe which API versions a service implements, and the library resolves the incoming request to the right one. The README describes the result as simple metadata attributes and conventions, and states that you do not need to learn new routing concepts or change how services are implemented.

The target audience is narrow but real. It is for teams running ASP.NET services that must support more than one version at the same time, including teams migrating services that never had versioning before. The library covers Minimal APIs, MVC on ASP.NET Core, gRPC, OData v4.0, and classic Web API, each with its own NuGet package. That breadth is the point: the same versioning vocabulary applies whether your endpoint is a Minimal API route or a gRPC service.

The default configuration follows the versioning semantics in the Microsoft REST Guidelines. That matters because it means the out-of-the-box behavior is not arbitrary. If your organization already follows those guidelines, the defaults should match expectations. If it does not, the README is explicit that customization and extension points exist for services with different semantics, which is the escape hatch for teams carrying legacy versioning conventions they cannot change.

## How version resolution works across the supported flavors

The architecture separates two concerns. First, metadata: attributes and conventions declare which API versions a given service or endpoint implements. Second, resolution: at request time the library reads the requested version from the request and selects the matching endpoint. The README frames the whole thing as adding versioning semantics to existing services, which is why the metadata layer sits alongside normal routing rather than replacing it. Your existing route templates, filters and model binding keep working.

Because each ASP.NET flavor has a separate package, the resolution pipeline is wired per hosting model. Asp.Versioning.Http covers Minimal APIs, Asp.Versioning.Mvc covers MVC, Asp.Versioning.Grpc covers gRPC, and Asp.Versioning.OData covers OData v4.0. There are also classic Web API packages for the older stack. Choosing the wrong package for your hosting model is the first failure mode a new user hits, and the README's package list is the only reliable map. The packages are not interchangeable wrappers around one core; they integrate with different endpoint models.

Documentation is a second pipeline. The repository also hosts API explorers for OpenAPI, with Asp.Versioning.OpenApi and Asp.Versioning.Mvc.ApiExplorer listed as separate packages. That separation tells you something important: versioning your endpoints and versioning your API description are related but distinct steps. If you emit OpenAPI documents, you need the explorer package in addition to the core versioning package, and you should expect to configure how versions map to documents yourself. Nothing in the README suggests the explorer infers a document-per-version layout without configuration.

## Getting the right package and following the quick start

The README does not print installation commands. It gives one thing per flavor: the NuGet package name, a quick start link, and a link to example code in the repository. That is the intended path, and it is worth following in that order.

For a Minimal API application, the package is Asp.Versioning.Http, and the README links a quick start at the new services page under the Minimal API anchor. The NuGet package page is where the install command lives, since the README only shows the badge and the package name:

```bash
dotnet add package Asp.Versioning.Http
```

The same pattern holds for the other flavors. Asp.Versioning.Mvc for ASP.NET Core MVC, Asp.Versioning.Grpc for gRPC, Asp.Versioning.OData for ASP.NET Core with OData v4.0, and Asp.Versioning.WebApi plus Asp.Versioning.WebApi.OData for classic Web API. Each row in the README carries its own quick start link, and the MVC and OData flavors share the new services quick start page with different anchors. Copying a Minimal API example into an MVC project will not work, because the registration and attribute surface differ.

For working code rather than prose, the repository ships examples. The ASP.NET Core examples live under examples/AspNetCore/WebApi, the OData examples under examples/AspNetCore/OData, the classic Web API examples under examples/AspNet/WebApi, and there is a dedicated OpenAPI sample at examples/AspNetCore/WebApi/OpenApiSample. Those directories are the reference to read before you write your own configuration, since the README itself stops at the package table.

## Where the design pushes work back onto you

The library decides which version a request is asking for, but it does not decide what a version means for your data. Nothing in the README promises compatibility checking, deprecation scheduling, or response transformation between versions. If version 1 returns a field that version 2 removes, you write both endpoints. The metadata tells the router which one to hit; it does not reconcile the payloads, and it will not warn you when two versions drift apart in behavior.

The classic Web API packages are a second boundary. They exist for the older ASP.NET stack, and the README lists them alongside the Core packages without suggesting feature parity. Teams on classic Web API should treat the Core documentation and quick starts as a different product line, and check the classic-specific quick start page instead. Reading a Core example and assuming the same configuration keys exist on the classic stack is a plausible way to lose an afternoon.

A third limitation is documentation coverage in the README itself. It lists packages, quick starts, and examples, but it does not document rollback behavior, version retirement, or what happens to clients pinned to a removed version. Those answers live in the docs site and the wiki directory, not in the repository front page. Anyone evaluating the library from the README alone will overestimate how much of the versioning lifecycle is handled for them. The mechanism is solid; the lifecycle policy is yours.

## How it differs from hand-rolled route versioning

The obvious alternative is manual route prefixes: put /v1 and /v2 in your route templates and register separate handlers. The difference is where the version lives. With manual prefixes the version is part of the URL string, and every piece of tooling that touches your routes has to parse it. With ASP.NET API Versioning the version is metadata attached to the endpoint, and the URL shape is a configuration choice rather than a hard-coded convention.

That distinction shows up when versioning requirements change. If you later need to accept the version from a header or a query string as well as the path, a manual scheme means rewriting route templates and every client contract. With this library the version is resolved before endpoint selection, so the source of the version is a configuration concern. The README's emphasis on customization and extension points for services with non-standard semantics is aimed exactly at this case, and it is the strongest argument for the library over a naming convention.

A second alternative is doing nothing and freezing the API. That is a legitimate choice for internal services with a small, coordinated set of consumers. The library earns its place when consumers are external, when versions must coexist for a long period, or when you need per-version OpenAPI documents. For a single internal consumer that deploys in lockstep with the service, the configuration and the extra packages are overhead with no payoff. The decision is about consumer count and release coupling, not about how modern your stack is.

## Maintenance, licensing and upgrade cost

The repository is not archived, and the last push was on 2026-09-07. The most recent release listed is v10.2.0 on 2026-08-06, following v10.0.0 on 2026-04-21 and a preview in March 2026. That release cadence suggests the project tracks current ASP.NET versions rather than sitting on an old baseline, though the README does not state a support policy or a minimum framework version. If you are on an older .NET release, confirm compatibility from the package metadata on NuGet rather than assuming the latest version works for you.

The licence is MIT, per the LICENSE.txt file and the badge at the top of the README. MIT is permissive: you can use the packages in closed-source and commercial services, and there is no copyleft obligation on your own code. This is not legal advice, and if your organization has rules about which licences are acceptable, check the full text in LICENSE.txt rather than the badge.

Upgrade cost is dominated by the ASP.NET version you target, not by the library's own API surface. The v10 line aligns with the current .NET release cycle, and the repository ships a global.json and a Directory.Packages.props under examples, which is where version pinning lives in a .NET solution. Expect to move the package reference in step with your framework upgrade. The README does not document a migration guide for jumping between major versions, so read the release notes for each major before upgrading a production service.

## Versioned OpenAPI and where the documentation stops

The API explorer packages are the part most teams underestimate. Asp.Versioning.OpenApi and Asp.Versioning.Mvc.ApiExplorer are listed as separate NuGet packages from the core versioning libraries, and the README describes them as adding additional OpenAPI support. The word additional is doing work: the core packages version your endpoints, and these packages exist to make the OpenAPI output aware of those versions.

There is an example project in the repository at examples/AspNetCore/WebApi/OpenApiSample, which is the concrete reference for wiring this up. The README also links a docs overview with anchors for Minimal API or MVC Core, which is where the explorer configuration is described. If you generate client SDKs from OpenAPI, this is the part you cannot skip. A single merged document that hides version differences will produce clients that compile against the wrong shape, and the failure surfaces at runtime in a consumer's code rather than in your build.

What the README does not cover is how many documents you should emit, or how consumers should discover which versions exist. Those are design decisions the library leaves to you. It is also silent on whether a deprecated version should still appear in the generated document. The honest summary is that ASP.NET API Versioning gives you the mechanism for describing and resolving versions, and the OpenAPI packages give you a way to reflect that in your API description. The policy layer, meaning which versions you publish and for how long, remains your problem.

## Conclusion

Adopt ASP.NET API Versioning if you run ASP.NET services that already have or expect more than one live API version, and you want the versioning rules expressed as attributes and conventions rather than hand-rolled routing. Do not adopt it if you have a single version and no roadmap for a second, or if you need the version reported somewhere the library does not wire up, since you would carry the configuration cost for nothing. Before committing, verify three things: that the package for your flavor (Asp.Versioning.Http, Asp.Versioning.Mvc, Asp.Versioning.Grpc, Asp.Versioning.OData) matches your hosting model, that your chosen version reading method behaves the way you expect in a real request, and that your OpenAPI output is split per version if clients depend on it. The README does not document rollback, so plan your versioning scheme before you ship the first public version.

## FAQ

### What is API versioning in ASP.NET Core?

It is the practice of letting a single ASP.NET Core service expose more than one version of its API at the same time. ASP.NET API Versioning implements this by letting you declare which versions a service implements through metadata attributes and conventions, then resolving each incoming request to the matching version.

### How do you do API versioning with ASP.NET API Versioning?

You add the NuGet package for your hosting flavor, such as Asp.Versioning.Http for Minimal APIs, register the versioning services, and annotate your endpoints with version metadata. The README states the default configuration follows the versioning semantics in the Microsoft REST Guidelines, and that you do not need to learn new routing concepts.

### Why is API versioning needed?

Because services change while clients cannot always change with them. Keeping multiple versions live lets existing consumers keep working while new consumers use the updated contract. ASP.NET API Versioning exists specifically for services that need to support more than one version, including ones that never had versioning before.

## Sources

- [dotnet/aspnet-api-versioning on GitHub](https://github.com/dotnet/aspnet-api-versioning)
- [Issues](https://github.com/dotnet/aspnet-api-versioning/issues)
- [License: MIT](https://github.com/dotnet/aspnet-api-versioning/blob/main/LICENSE)
- [README](https://github.com/dotnet/aspnet-api-versioning/blob/main/README.md)
- [Releases](https://github.com/dotnet/aspnet-api-versioning/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/dotnet-aspnet-api-versioning
