This is part four in a series of blogs about common tasks you'll encounter when updating Umbraco 13 to 16. In this part, we'll look into updating Umbraco API controllers to Umbraco 16. We'll cover the UmbracoApiController
and the UmbracoAuthorizedApiController
, because both of them no longer exist in Umbraco 16.
Update UmbracoApiControllers
The UmbracoApiController
is a controller for creating your own Web API endpoints. There really wasn't much special about these controllers, except that they were routed automatically to a certain URL. As an example, take this endpoint:
public class ExampleController : UmbracoApiController
{
public string HelloWorld()
{
return "Hello World!";
}
}
It would be routed to ~/Umbraco/Api/Example/HelloWorld
.
Umbraco likely recognized that an UmbracoApiController
isn’t very special, so it was replaced with regular controllers where you are responsible for defining the routing yourself. Umbraco has documentation for porting over old Umbraco API Controllers, so I’ll just refer you to that.
Update UmbracoAuthorizedApiControllers
The changes to the UmbracoAuthorizedApiController
are more significant. These controllers were meant to be used by extensions in the Umbraco backoffice and could only be called in the context of a logged-in user. You could think of them as backoffice API endpoints
.
Cue the Management API
With the new Umbraco 14+ backoffice, the Management API was introduced as a uniform way for the frontend to communicate with the backend. Compared to Umbraco 13, this is like backoffice API endpoints in steroids! To use custom endpoints for your backoffice extensions, you now add them to the Management API. So we need to change our UmbracoAuthorizedApiControllers
to use the Management API.
As an example, here’s a small API endpoint in Umbraco 13 that creates a new website in the content tree. We’ll update this to Umbraco 16:
[PluginController("CoreContent")]
public class CoreContentDashboardApiController(...)
: UmbracoAuthorizedApiController
{
[HttpGet]
public IActionResult CreateNewWebsite(string websiteName)
{
...
}
}
Perform the update
First, change the base class from UmbracoAuthorizedApiController
to ManagementApiControllerBase
:
public class CoreContentDashboardApiController(...)
: ManagementApiControllerBase
Second, remove the PluginController
attribute and replace it with VersionedApiBackOfficeRoute
and ApiExplorerSettings
:
[VersionedApiBackOfficeRoute("core-content")]
[ApiExplorerSettings(GroupName = "ProudNerds Core")]
public class CoreContentDashboardApiController(...)
: ManagementApiControllerBase
So what did we add?
VersionedApiBackOfficeRoute
determines the last part of the URL. To stay consistent with the rest of the Management API, use lowercase letters and separate words with a dash. In this example, the base URL of the endpoints will be/umbraco/management/api/v1/core-content
.ApiExplorerSettings
with aGroupName
ensures a separate section with that title will appear in the Swagger docs of the Management API.
The individual endpoints don’t need many changes, but keep these caveats and tips in mind:
Umbraco uses a single responsibility per controller in their source code, so typically you’ll have one endpoint per controller. If you place multiple endpoints in a single controller, you need to supply a template for the
HttpGet
(or other HTTP method) to make sure the endpoints are unique, for example[HttpGet("create-new-website")]
.Add
ProducesResponseType
attributes to enhance the Swagger docs. But avoid adding response types for common codes like 400 and 404, as this will break Swagger because Umbraco already registers those internally.
So a complete API could look like this:
[VersionedApiBackOfficeRoute("core-content/create-new-website")]
[ApiExplorerSettings(GroupName = "ProudNerds Core")]
public class CoreContentDashboardApiController(...)
: ManagementApiControllerBase
{
// Because this controller has only one endpoint,
// we don’t need to set a template on the HttpGet.
// The VersionedApiBackOfficeRoute determines the endpoint.
[HttpGet]
[ProducesResponseType<int>(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType<ProblemDetails>(StatusCodes.Status500InternalServerError)]
public IActionResult CreateNewWebsite(string websiteName)
{
...
}
}
This will add a section in Swagger of the Management API with our custom endpoint:
Granular security
By default, Management API endpoints are accessible to any logged-in Umbraco user. However, sometimes you need to restrict access to specific roles or policies. That’s where the Authorize
attribute comes in:
[Authorize(Policy = AuthorizationPolicies.RequireAdminAccess)]
[VersionedApiBackOfficeRoute("core-content")]
[ApiExplorerSettings(GroupName = "ProudNerds Core")]
public class CoreContentDashboardApiController(...)
: ManagementApiControllerBase
{
...
}
In this example, the endpoint is only accessible to administrators.
The documentation for creating a backoffice API has more information and a more elaborate example.
Summary
Updating Umbraco APIs isn’t difficult once you know what to look for:
- Replace
UmbracoApiController
usage with regular controllers and wire up routing yourself. - Replace
UmbracoAuthorizedApiController
withManagementApiControllerBase
, addVersionedApiBackOfficeRoute
andApiExplorerSettings
, and secure endpoints withAuthorize
when needed.
Top comments (0)