HomeDev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunitySubmit a ticketLog In
GitHubNuGetDev CommunitySubmit a ticket

Customize for edit view

Describes how to configure edit view for displaying content in the Optimizely Content Delivery API.

Return draft and expired content

From Optimizely Content Delivery API 2.6.0, draft and expired content is not returned by Content Delivery API by default. If you try to retrieve a draft or expired content, you will probably get a 404 Not Found. This is convenient when you use Content Delivery API to build a Single-Page Application (SPA) for view mode and when the client should not care about the draft or expired page – as in a standard Alloy site. However, in edit view, you may want to get content, including the draft and expired content. Content Delivery API lets you customize its ContentLoaderService to achieve this.

First, create a class CustomContentLoaderService derived from ContentLoaderService; and within this class, override the function ShouldContentBeExposed. Finally, register a class as the default service for ContentLoaderService in Startup.cs.


services.AddTransient < ContentLoaderService, CustomContentLoaderService > ();
public class CustomContentLoaderService: ContentLoaderService {
  private readonly EPiServer.Web.IContextModeResolver _contentModeResolver;

  public CustomContentLoaderService(
    IContentLoader contentLoader,
    IPermanentLinkMapper permanentLinkMapper,
    IContentProviderManager providerManager,
    IPublishedStateAssessor publishedStateAssessor,
    EPiServer.Web.IContextModeResolver contentModeResolver
  ): base(contentLoader, permanentLinkMapper, providerManager, publishedStateAssessor) {
    _contentModeResolver = contentModeResolver;

  protected override bool ShouldContentBeExposed(IContent content) {
    //In EditMode, unpublished or expired content is still returned
    if (_contentModeResolver.CurrentMode == ContextMode.Edit) {
      return true;

    return base.ShouldContentBeExposed(content);

 Resolve URL based on context

When you fetch content from Content Delivery API, there is a URL property that contains the CMS-friendly URL of the requested content (for example, /en/artists/). However, the content URL is different in edit view. If you want to get the right URL in edit view, like on the Alloy site, you should override the UrlResolverService to resolve the correct URL of the content based on the current request context.

  • Create a class called CustomUrlResolverService that derived from UrlResolverService, and override the ResolveUrl method.
  • Register this class as the default service for UrlResolverService in InitializableModule.


public void ConfigureContainer(ServiceConfigurationContext context) {
  context.Services.AddSingleton < UrlResolverService, CustomUrlResolverService > ();

public class CustomUrlResolverService: UrlResolverService {
  private readonly ServiceAccessor < HttpContextBase > _httpContextAccessor;
  public CustomUrlResolverService(UrlResolver urlResolver,
    ContentApiConfiguration contentApiConfiguration,
    ServiceAccessor < HttpContextBase > httpContextAccessor): base(urlResolver, contentApiConfiguration) {
    _httpContextAccessor = httpContextAccessor;
  public override string ResolveUrl(ContentReference contentLink, string language) {
    return _urlResolver.GetUrl(contentLink, language, new VirtualPathArguments {
      ContextMode = GetContextMode()
  private ContextMode GetContextMode() {
    var httpCtx = _httpContextAccessor();
    if (httpCtx == null || httpCtx.Request == null || httpCtx.Request.QueryString[PageEditing.EpiEditMode] == null) {
      return ContextMode.Default;
    if (bool.TryParse(httpCtx.Request.QueryString[PageEditing.EpiEditMode], out bool editMode)) {
      return editMode ? ContextMode.Edit : ContextMode.Preview;
    return ContextMode.Undefined;


 Impersonate visitor group

Content Delivery API default filters content based on the user's visitor group. You may want to send a visitor group ID in request parameters and use this ID to filter content. A use case is, for example, the preview in CMS. You can change the visitor group ID in the drop-down menu, and the page is displayed as viewed by the selected visitor group.


When using Content Delivery API to build a SPA edit view, you can add a custom filter to make Content Delivery API filter content based on the visitor group retrieved from the request context.

  • First, create a class called ImpersonateVGFilter that implement IContentFilter.
  • Register the ImpersonateVGFilter in your service container.
public class ImpersonateVGFilter: IContentFilter {
  private readonly IHttpContextAccessor _httpContextAccessor;

  public ImpersonateVGFilter(IHttpContextAccessor httpContextAccessor) {
    _httpContextAccessor = httpContextAccessor ??
      throw new ArgumentNullException(nameof(httpContextAccessor));

  public Type HandledContentModel => typeof (IContent);

  public void Filter(IContent content, ConverterContext converterContext) {
    var visitorGroupId = _httpContextAccessor.HttpContext.Request.Query[VisitorGroupRole.VisitorGroupKeyByID];

    if (!string.IsNullOrEmpty(visitorGroupId)) {
      // setup impersonate visitor group
      _httpContextAccessor.HttpContext.SetupVisitorGroupImpersonation(content, AccessLevel.Read);
services.TryAddEnumerable(ServiceDescriptor.Singleton < IContentFilter, ImpersonateVGFilter > ());