Loading...
Area: Episerver Content Delivery API
Applies to versions: 2 and higher

Getting started

Recommendations [hide]

In this topic

Installation

Episerver Content Delivery API consists one main NuGet package, EPiServer.ContentDeliveryApi.Core, and a number of additional NuGet packages, allowing you as a developer to install only the functionality you need. The different packages are described in detail in Installing Content Delivery API, but in short, these are the additional packages:

  • EPiServer.ContentDeliveryApi.Cms. You can install just this package if you only need to deliver content using frameworks like React or Vue, without authentication or search capabilities in the API.
  • Episerver.ContentDeliveryApi. Install this package if you are going to build front-end on mobile platforms.
  • EPiServer.ContentDeliveryApi.OAuth. Install this package if you need OAuth authentication.
  • EPiServer.ContentDeliveryApi.Search..Install this package if you need search capabilities in the API. Note that search requires an Episerver Search & Navigation (formerly Episerver Find) installation and licence. If you do not already have a licence for Search & Navigation, you can get one at the Episerver Marketplace. (Licences for demo purposes can be found at Episerver Search & Navigation - Developer Demo Services/).

Install the NuGet packages in your solution using the NuGet Package Manager in Visual Studio or via command line:

Install-Package EPiServer.ContentDeliveryApi

Adding search

If you have added the EPiServer.ContentDeliveryApi.Search package, you need to install Episerver Search & Navigation and also add a licence for that.

By installing both the CMS and the Search package, (HttpConfiguration)config.MapHttpAttributeRoutes() is called twice. To fix this, add the following to your <appSettings>:

<add key="episerver:contentdeliverysearch:maphttpattributeroutes" value="false" />

Note: If you are running the Service API, you may have to disable settings for the CMS package as well. See Default HttpConfiguration for more details.

Setting access rights

For security reasons, the Content Delivery API is not publicly exposed by default. When you have installed the relavant NuGet packages, you need to give the ContentApiRead role Read access to the start page and, if the whole site is available to the API, all its children. You can do this in admin view under Set Access Rights

Note: You should not expose content that contains secure information, such as API keys.

Configuring Content Delivery API options

Configure the API and make it public in an initalization module like this:

[InitializableModule]
[ModuleDependency(typeof(ServiceContainerInitialization), typeof(ContentApiCmsInitialization))]
public class ContentApiInitialization : IConfigurableModule
{
	public void ConfigureContainer(ServiceConfigurationContext context)
	{
		context.Services.AddTransient<RoutingEventHandler, CustomContentApiRoutingEventHandler>();
		

		// set minimumRoles to empty to allow anonymous calls (for visitors to view site in view mode)
		context.Services.Configure<ContentApiConfiguration>(config =>
		{
			config.Default()
				.SetMinimumRoles(string.Empty)
				.SetSiteDefinitionApiEnabled(true);
		});
	}
}

If you do not make the API public, client JavaScript cannot anonymously consume the API and you will be required to log in when requesting the API from a REST client.

Site definition API

The initialization module you created in the previous step also enables a special site definition API which is useful for debugging scenarios. The site definition API is accessed by:

https://www.mywebsite.com/api/site/?language=en

The site definition API returns data such as siteSettings, language selectors and currencies. You can query the API for specific pages or blocks, like this:

http://www.mywebsite.com/api/episerver/v2.0/content/{contentID}/

The content, if it exists, is returned in JSON format, for example, like this:

{
	contentLink: {},
	name: "About us",
	language: {},
	existingLanguages: null,
	masterLanguage: {},
	contentType: [],
	parentLink: {}
}

Depending on your data and what you want to achieve, some customization might be needed.

Serialization

When data is requested, Content Delivery API serializes the data, that is IContent is turned into JSON, before it is returned to the client.

Serialization.png

For more information, see Serialization.

Re-index Search & Navigation

If you are setting up a site from the beginning, this step is unnecessary, but for existing sites with existing content, you should run the EPiServer Find Content Indexing Job in admin view to make sure your content is properly re-indexed.

Testing and verifying the API

At this point, you should have these endpoints available on your host site:

# POST/GET Endpoint Description
1 POST /api/episerver/auth/token Authorization (Note: Only accessible if you have installed the EPiServer.ContentDeliveryApi.OAuth NuGet package.)
2 GET /api/episerver/auth/token Authorization (Note: Only accessible if you have installed the EPiServer.ContentDeliveryApi.OAuth NuGet package.)
3 GET /api/episerver/auth/token Get new access token by using refresh token (Note: Only accessible if you have installed the EPiServer.ContentDeliveryApi.OAuth NuGet package.)
4 GET /api/episerver/v2.0/content Retrieve multiple content items
5 GET /api/episerver/v2.0/content/{referenceORguid} Retrieve content by content reference or content guid
6 GET /api/episerver/v2.0/content/{reference}/children Retrieve child content of a content reference
7 GET /api/episerver/v2.0/content/{reference}/ancestors Retrieve ancestor content for a content reference
8 GET /api/episerver/v2.0/site Retrieve a list of sites in the system and their associated properties

To verify that the API is working properly, open the Site Definition API in your browser:

http://<your-site-url>/api/episerver/v2.0/site/

You should now get a 200 OK response and see the site and its associated properties:

[
   {
      "name":"ContentDeliveryAPI",
      "id":"124a76ca-932c-4e0d-a6e0-ae82f1a11899",
      "contentRoots":{
         "contentAssetsRoot":{
            "id":4,
            "workId":0,
            "guidValue":"99d57529-61f2-47c0-80c0-f91eca6af1ac",
            "providerName":null,
            "url":null,
            "expanded":null
         },
         "globalAssetsRoot":{
            "id":3,
            "workId":0,
            "guidValue":"e56f85d0-e833-4e02-976a-2d11fe4d598c",
            "providerName":null,
            "url":null,
            "expanded":null
         },
         "rootPage":{
            "id":1,
            "workId":0,
            "guidValue":"43f936c9-9b23-4ea3-97b2-61c538ad07c9",
            "providerName":null,
            "url":null,
            "expanded":null
         },
         "wasteBasket":{
            "id":2,
            "workId":0,
            "guidValue":"2f40ba47-f4fc-47ae-a244-0b909d4cf988",
            "providerName":null,
            "url":null,
            "expanded":null
         },
         "startPage":{
            "id":5,
            "workId":0,
            "guidValue":"3c745ea7-390c-4878-a11b-9f4cb1204e6e",
            "providerName":null,
            "url":"/en/",
            "expanded":null
         }
      },
      "languages":[
         {
            "isMasterLanguage":true,
            "urlSegment":"en",
            "displayName":"English",
            "name":"en"
         },
         {
            "isMasterLanguage":false,
            "urlSegment":"sv",
            "displayName":"Swedish",
            "name":"sv"
         }
      ],
      "hosts":[
         {
            "name":"localhost:60238",
            "type":"Undefined",
            "language":null
         },
         {
            "name":"*",
            "type":"Undefined",
            "language":null
         }
      ]
   }
]

Using Postman

Postman is a free tool that can be used as an API client to send REST calls. With Postman, you can connect to APIs and simulate calls to endpoints and their responses without having to set up a backend server.

To test the Content Delivery API, you have to use Postman and send a request to one of the endpoints mentions in the above section.

Note that you should disable MinimumRole and RequiredRole in Content Delivery API (see Map RequiredRole to group roles in Configuration) for easier testing with Postman, otherwise you will need to install the OAuth package and send a bearer token along in the header to get the data.

Personalizing content using Episerver Content Delivery API

How do you add content personalization to a headless solution where the tracking does not hit a controller in the presentation layer?  You can use a headless approach for content recommendations through the Content Delivery API. To do this you need to implement compatible tracking and calls to the recommendation API. See Tracking and Advance API.

In a headless scenario, you can also customize the DefaultContentModelMapper and replace it with your own. See How to customize API to change data returned to clients and Serialization.

Note: The DefaultContentModelMapper is currently marked as internal, so there is a risk of unadvertised breaking changes when customizing this.

Full SPA demo 

On GitHub you can find demo site called Music Festival. It is a Single-Page Application (SPA) site built on Episerver Content Delivery API and Vue.js, and includes some customizations for friendly URLs and flatter JSON results. 

MusicFestival.png

On GitHub, you can also find an initial alpha release of a React-based SPA on top of the demo site Episerver Foundation.

Blog posts on SPA applications

Troubleshooting

General troubleshooting steps

  • Clear your temporary ASP.net files.
  • For troubleshooting purposes, you can prevent site/IIS caching by setting optimizeCompilations to false under <system.web>.
    <compilation debug="true" targetFramework="4.6.1" optimizeCompilations="false" />​

    After troubleshooting, revert the optimizeCompilations setting by setting it to true as default.

Common errors

404 - ContentNotFound when trying to get content with Content Delivery 

  • Does the 'Content Api Access' role have Read access?
    The Content Delivery API implementation uses a RequiredRole property, and this role is used by the ContentApiController (the one responding to your content requests) to filter your content. If this does not have access to the content, the response will result in a 404 - ContentNotFound. See Setting access.
  • Is the Content Delivery API initialized properly?
    The Content Delivery API uses a constructor injection of the IContentApiOptions implementation, but this only works if there actually is an implementation to inject. There are two extension methods for this on the ServiceConfigurationContext object. See Configuring Content Delivery API options.
  • Do you use the correct Accept-Language header?
    Content Delivery API returns content based on the language passed in the Accept-Language header. The Accept-Language header should be used to specify the locale variant of content that the client prefers (see Mozilla - MDN Web Docs for more information).
    The problem is some browsers, like Chrome for example, automatically adds its preferred language to the Accept-Language header, if the header value is not manually set by the user. In this case, the client should manually pass the Accept-Language header to prevent the browser from adding its own header value.
    If you are using the Content Delivery API in an AJAX application, you can specify/override the Accept-Language header value in your front-end code. See this external blog post for a code sample.

404 Http Error when sending request to Content Delivery endpoints

  • Have you installed both the CMS and the Search packages? 
    In this case, (HttpConfiguration)config.MapHttpAttributeRoutes() is called twice and a 404 error is thrown. See Adding search.
    Also, re-index the site after installing the Search package in case you get a 404.
  • Are you using friendly URLs?
    If you are using configuration handlers in your web.config like in the example below, Content Delivery API friendly URLs will throw a 404. Reverse the order of handlers or try and remove the StaticFileHandler.
    <add name="StaticFileHandler" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" />
    <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />​
    Also note that friendly URLs may not work with simple addresses.

404 Http Error when sending request to /token endpoint in EPiServer.ContentDeliveryApi.OAuth

Make sure you have added the following lines at the bottom in Startup.cs file (see OAuth Configuration).

//// Episerver Content API Authorization
app.UseContentApiIdentityOAuthAuthorization<ApplicationUserManager<ApplicationUser>, ApplicationUser>(new ContentApiOAuthOptions()
{
RequireSsl = false
});​

500 Internal Server error when using both Content Delivery API and the Service API

The Service API uses UseServiceApiIdentityTokenAuthorization() and the Content Delivery API uses UseContentApiIdentityOAuthAuthorization(), and both these use the OWIN OAuthAuthorizationServerProvider under the hood. If you register both methods, OWIN will throw an exception because of duplicated OAuth provider.

However, because both APIs use OWIN OAuth middleware, you do not need to register both methods. Use whichever method you prefer and retrieve the token. After that, you should be able to use this token to authenticate with both Service API and Content Delivery API. Make sure that your user has sufficient privileges to access both APIs.

CustomContentDeliveryService is not triggered

The CustomContentDeliveryService only works with Content Delivery API version 2.6.1 and lower. For versions 2.9 and higher, you should implement IContentApiModelFilter and set the base properties to null:

[ServiceConfiguration(typeof(IContentApiModelFilter), Lifecycle = ServiceInstanceScope.Singleton)]
    public class CustomContentApiModelFilter : ContentApiModelFilter<ContentApiModel>
    {
        public override void Filter(ContentApiModel contentApiModel, ConverterContext converterContext)
        {
            // Set the properties to null here 
        }
    }​

From version 3, another way is to use the select parameter in the endpoints to filter out properties, see the Content Delivery API SDK. Note: v3 endpoints are still in preview state.

I cannot get my images from my content

Use a property model converter (IPropertyModelConverter) which allows you to customize the output sent to the Content Delivery API. An example can be seen in the Music Festical project. See also Serialization and How to customize API to change data returned to clients.

Frequently Asked Questions

How do I post to the Content Delivery API?

The Content Delivery API does not currently support POST or PUT of content. If you need your users to save information, you may need to create your own API and storage repository.

How should I use custom routing?

Make sure that your custom routing and and Content Delivery API's custom routing do not conflict with each other.

This can disrupt other partial routers in the site because the request URL is rewritten. To solve this problem, follow these steps:

  • Create a new class (for example, CustomContentApiRouteService) that inherits ContentApiRouteService and then, register a transient lifecycled implementation for a ContentApiRouteService in the initialization service.

  • Override the function ShouldRouteRequest to prevent the URL from being re-written in unexpected cases. For example, requests whose accept types contain application/json are currently handled by our partial router (accept type application/json is a common header). So, you can add one more header (for example, Routed-By-ContentApi) for CD-related requests and then, use this header in the function to decide whether our partial router should handle the request and rewrite URL later on.

    using EPiServer.ContentApi.Routing;
    using System.Web;
    
    public class CustomContentApiRouteService : ContentApiRouteService
    {
        public override bool ShouldRouteRequest(HttpRequestBase request)
        {
            // By default, Requests which have accept headers 'application/json' will be routed.
            //if (request != null && request.AcceptTypes?.Contains(RouteConstants.JsonContentType) == true)
            //{
            //    return true;
            //}
    
            bool isRoutedByContentApi = false;
            if (bool.TryParse(request.Headers["Route-By-ContentApi"], out isRoutedByContentApi))
            {
                return isRoutedByContentApi;
            }
    
            return false;
        }
    }

Can I use Content Delivery API with SQL/Windows membership?

Content Delivery API OAuth package does not support SQL/Windows membership. Use Asp.Net Identity for authentication.

Related information

Blog posts

Do you find this information helpful? Please log in to provide feedback.

Last updated: Jul 02, 2020

Recommendations [hide]