All APIs register as version 1.0 by default, which means their endpoints are routed under /umbraco/management/api/v1/.
As projects evolve, adding new versions of your APIs sometimes becomes necessary. Multiple versions of the same API can co-exist to retain backward compatibility.
APIs are versioned using attribute annotation:
[ApiVersion] attributes on the API controllers.
[MapToApiVersion] attributes on the API controller actions.
It is recommended to annotate all API controller actions, as well as the version 1.0 actions.
Using the API controller from the Creating your own API article as an example, we can add version 2.0 implementations of select actions:
MyItemApiController.cs
[ApiVersion("1.0")][ApiVersion("2.0")]publicclassMyItemApiController:ManagementApiControllerBase{ [HttpGet] [MapToApiVersion("1.0")]publicIActionResultGetAllItems(int skip =0,int take =10) { // ... } [HttpGet("{id:guid}")] [MapToApiVersion("1.0")]publicIActionResultGetItem(Guid id) { // ... } [HttpPost] [MapToApiVersion("1.0")]publicIActionResultCreateItem(string value) { // ... } [HttpPut("{id:guid}")] [MapToApiVersion("1.0")]publicIActionResultUpdateItem(Guid id,string value) { // ... } [HttpDelete("{id:guid}")] [MapToApiVersion("1.0")]publicIActionResultDeleteItem(Guid id) { // ... } [HttpGet("{id:guid}")] [MapToApiVersion("2.0")]publicIActionResultGetItemV2(Guid id) {MyItem? item =AllItems.FirstOrDefault(item =>item.Id== id);return item isnotnull?Ok(item):OperationStatusResult(MyItemOperationStatus.NotFound, builder =>NotFound( builder .WithTitle("The item was not found") .WithDetail("The item with the given ID did not exist.") .Build() ) ); } [HttpPost] [MapToApiVersion("2.0")]publicIActionResultCreateItemV2(string value) {var newItem =newMyItem(value);AllItems.Add(newItem);returnCreatedAtId<MyItemApiController>( ctrl =>nameof(ctrl.GetItemV2),newItem.Id ); }}
Version 2.0 of the "get" and "create" endpoints - GetItemV2 and CreateItemV2 respectively, are added with the code above. The rest of the endpoints remain version 1.0 only.
The version 2.0 endpoints are routed under /umbraco/management/api/v2/.
In the example above, the version 2.0 actions are added to the same API controller as their version 1.0 counterparts. If you prefer, they can be added to a new API controller instead. This will leave you with separate API controllers, one for each version of the API. See the examples below:
With the version 1.0 actions added in a controller sampled above, the version 2.0 actions are added in a new controller, as shown below.
MyItemApiVersionTwoController.cs
[ApiVersion("2.0")]publicclassMyItemApiVersionTwoController:ManagementApiControllerBase{privatestaticreadonlyList<MyItem> AllItems =Enumerable.Range(1,100) .Select(i =>newMyItem($"My V2 Item #{i}")) .ToList(); [HttpGet("{id:guid}")] [MapToApiVersion("2.0")]publicIActionResultGetItem(Guid id) {MyItem? item =AllItems.FirstOrDefault(item =>item.Id== id);return item isnotnull?Ok(item):OperationStatusResult(MyItemOperationStatus.NotFound, builder =>NotFound( builder .WithTitle("The item was not found") .WithDetail("The item with the given ID did not exist.") .Build() ) ); } [HttpPost] [MapToApiVersion("2.0")]publicIActionResultCreateItem(string value) {var newItem =newMyItem(value);AllItems.Add(newItem);returnCreatedAtId<MyItemApiVersionTwoController>( ctrl =>nameof(ctrl.GetItem),newItem.Id ); }}
While perhaps tempting, do not name your API controller V2 - e.g. MyItemApiVersionV2. Due to an upstream issue in the API versioning system, this will currently cause routing issues in certain scenarios.