DEV Community

Cover image for Upgrade Umbraco 13 to 16: API controllers
Luuk Peters
Luuk Peters

Posted on

Upgrade Umbraco 13 to 16: API controllers

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!";
    }
}
Enter fullscreen mode Exit fullscreen mode

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)
    {
        ...
    }
}
Enter fullscreen mode Exit fullscreen mode

Perform the update

First, change the base class from UmbracoAuthorizedApiController to ManagementApiControllerBase:

public class CoreContentDashboardApiController(...) 
    : ManagementApiControllerBase
Enter fullscreen mode Exit fullscreen mode

Second, remove the PluginController attribute and replace it with VersionedApiBackOfficeRoute and ApiExplorerSettings:

[VersionedApiBackOfficeRoute("core-content")]
[ApiExplorerSettings(GroupName = "ProudNerds Core")]
public class CoreContentDashboardApiController(...) 
    : ManagementApiControllerBase
Enter fullscreen mode Exit fullscreen mode

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 a GroupName 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)
    {
        ...
    }
}
Enter fullscreen mode Exit fullscreen mode

This will add a section in Swagger of the Management API with our custom endpoint:

Endpoint as seen in Swagger in the Management API

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
{
    ...
}
Enter fullscreen mode Exit fullscreen mode

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 with ManagementApiControllerBase, add VersionedApiBackOfficeRoute and ApiExplorerSettings, and secure endpoints with Authorize when needed.

Top comments (0)