Atomic.Api for Umbraco

Quick info

Find here some of the most useful references related to Atomic.Api package for Umbraco.

Total downloads 1855
Last updated 2023-07-03
Supported Umbraco versions 11.4.0 and later
Umbraco Marketplace Link
Nuget Link
GitHub Link

Documentation

Introduction

Atomic.Api is an Atomic Toolkit packages which extends the default Umbraco API Controllers. It packs features which are often needed when developing API. Such features are:

  • Automatic resolving of the context culture based on parameters passed to the API controllers.
    Important when you have a multilanguage website, eliminating the need to pass a 'culture' parameter in all of your logic.
  • Preview content routes.
    We brought the Umbraco content previewing to the API and made it work smooth and feel native in the CMS.
  • Authorization.
    For both preview and default routes.
  • Umbraco context
  • More to come in the future.

Check out the Atomic.OutputCache package, which adds flexible caching to the API if this is something you need implemented in your solution.

Installation

It is important to choose the right version of Atomic.Api before adding it to your project. Atomic.Api versioning is coupled to the Umbraco version it is built for. This means that

Umbraco 11 works with Atomic.Api 11, 
Umbraco 12 works with Atomic.Api 12
and so on.

The code below assumes that Atomic.Api with latest version 12.0.0 is being installed on Umbraco 12, and you must adapt it according to your scenario.

The easiest way to get Atomic.Api installed is using the command line (CLI):

dotnet add package Atomic.Api --version 12.0.0

Atomic.Api can also be installed manually from NuGet using Visual Studio. If you need help with that approach, you can get more information here.

Overall, Atomic.Api is a NuGet package and supports all standard ways of installing NuGet packages.

Controllers

All Atomic.Api Controllers extend particular Umbraco API Controllers, which means that they provide all the default behavior coming from Umbraco. You can get detailed information about the Umbraco API Controllers here. Based on that, you can choose the right API Controller type you need for your implementation.

What Atomic.Api Controllers bring on top of Umbraco ones is:

  • Add an automatic context culture resolving based on a query string parameter
  • Add a Preview support
  • Add an Authorization support via HTTP Request Header
  • Add an IUmbracoContext available with the UmbracoContext property 

AtomicApiController

Extends UmbracoApiController

AtomicAuthorizedApiController

Extends UmbracoAuthorizedApiController

AtomicAuthorizedJsonController

Extends UmbracoAuthorizedJsonController

Context culture resolving

All Atomic.Api Controllers will automatically validate and set the context culture when you pass it via one of the following query string parameters:

  • culture
  • language
  • locale

Here are a couple of example URLs using the query string

https://example.com/products/13?culture=en_US
https://example.com/products/13?language=en_US
https://example.com/products/13?locale=en_US

If none of the available query string parameters fits to your solution, you can add a custom one as well. This can be done in the appsettings.json file by configuring the ApiParamsAffectingContextCulture:

 "Umbraco": {
    ...
  },
  "AtomicToolkit": {
    "Api": {
      "ApiParamsAffectingContextCulture": [ "SOMETHING_CUSTOM" ]
    }
  }

Preview

When you inherit from any of the Atomic.Api Controllers you will automatically get a preview route registered for all of your Actions. The preview route will automatically make your APIs return content which is not published, without you having to change anything in the code you have implemented. The cool part is that if you develop APIs which are used internally on your website, Umbraco will know to use the preview route in Umbraco preview mode and the default one otherwise. Check the LinkGenerator extension methods section for more info.

Preview routes need authorization in order to be accessed. Two authorization methods work with the preview routes. 

  • The user is logged in to Umbraco.
    This makes it easier when you are in the Umbraco preview mode, and you are previewing a page which makes calls to internal APIs developed with the Atomic.Api Controllers. Basically, you won't need to do anything, and it will just work.
  • A valid PreviewApiAuthToken is added to the HTTP request to your API
    This is useful when you expose your APIs to other systems. Check the Authorization section for more info.

What will the automatically added preview routes look like?

The preview routes basically add an "umbraco/preview" path in the beginning of the default ones. Let's have some examples.

Attribute routing:

[Route("products")]
public class ProductsController : AtomicApiController
{
    [Route("{id}")]
    public IActionResult Get(int id)
    {
        // Routes for product with ID=13 will be:
        // Default: "/products/13"
        // Preview: "/umbraco/preview/products/13"
    }
}

Default Umbraco routing:

public class ProductsController : AtomicApiController
{
    public IActionResult Get(int id)
    {
        // Routes for product with ID=13 will be:
        // Default: "/umbraco/api/products/get?id=13"
        // Preview: "/umbraco/preview/api/products/get?id=13"
    }
}

public class ProductsController : AtomicAuthorizedApiController // or AtomicAuthorizedJsonController
{
    public IActionResult Get(int id)
    {
        // Routes for product with ID=13 will be:
        // Default: "/umbraco/backoffice/api/products/get?id=13"
        // Preview: "/umbraco/preview/api/products/get?id=13"
    }
}

[PluginController("AwesomeProducts")]
public class ProductsController : AtomicApiController
{
    public IActionResult Get(int id)
    {
        // Routes for product with ID=13 will be:
        // Default: "/umbraco/awesomeproducts/products/get?id=13"
        // Preview: "/umbraco/preview/awesomeproducts/products/get?id=13"
    }
}

Of course, you don't need to remember or learn the routing mechanism because we have written some extension methods to the LinkGenerator which you can use.

Authorization

Token authorization for Preview API routes

By default, the access to the Preview API routes is restricted. In order to authorize a request, you either have to be logged in to Umbraco or add a valid PreviewApiAuthToken HTTP request header. The token value is configured in the appsettings.json file as follows: 

 "Umbraco": {
    ...
  },
  "AtomicToolkit": {
    "Api": {
      "PreviewApiAuthToken": "TOKEN_VALUE"
    }
  }

Token authorization for Default API routes

If you need to add a token authorization for your default API routes, you should only configure the PublicApiAuthToken in the appsettings.json file as follows:

"Umbraco": {
    ...
  },
  "AtomicToolkit": {
    "Api": {
      "PublicApiAuthToken": "TOKEN_VALUE"
    }
  }

LinkGenerator extension methods

Hard-coding API URL links to actions is bad. We can easily get API URL links using the built-in LinkGenerator. The Atomic.Api package adds two custom extension methods to the LinkGenerator. (information on how to use the LinkGenerator can be found in this blog post).

/// <summary>
/// Get the appropriate Atomic Api Url. It will also take into consideration if the controller supports Preview and return the Preview Url if Umbraco is in Preview mode.
/// </summary>
/// <typeparam name="T">T UmbracoApiController</typeparam>
/// <param name="linkGenerator">LinkGenerator</param>
/// <param name="httpContext">HttpContext</param>
/// <param name="actionSelector">Controller Action Selector</param>
/// <returns>Umbraco Api Url</returns>
public static string GetAtomicApiService<T>(this LinkGenerator linkGenerator, HttpContext httpContext, Expression<Func<T, object>> actionSelector) where T : UmbracoApiController, IAtomicApiController
{ ... }

/// <summary>
/// Get the Atomic Api Preview Url.
/// </summary>
/// <typeparam name="T">T UmbracoApiController, IAtomicUmbracoApiController</typeparam>
/// <param name="linkGenerator">LinkGenerator</param>
/// <param name="actionSelector">Controller Action Selector</param>
/// <returns>Umbraco Api Preview Url</returns>
public static string GetAtomicApiPreviewService<T>(this LinkGenerator linkGenerator, Expression<Func<T, object>> actionSelector) where T : UmbracoApiController, IAtomicApiController
{ ... }