HomeDev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunityDoc feedbackLog In
GitHubNuGetDev CommunityDoc feedback

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/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 all content, including the draft and expired content. Content Delivery API allows you to easily customize its ContentLoaderService to achieve this.

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

Example:

public void ConfigureContainer(ServiceConfigurationContext context)
  {
    context.Services.AddSingleton<ContentLoaderService, CustomContentLoaderService>();
  }
public class CustomContentLoaderService : ContentLoaderService
  {
    private readonly ServiceAccessor<HttpContextBase> _httpContextAccessor;
    public CustomContentLoaderService(IContentLoader contentLoader, ServiceAccessor<HttpContextBase> httpContextAccessor) : base(contentLoader)
      {
        _httpContextAccessor = httpContextAccessor;
      }
    protected override bool ShouldContentBeExposed(IContent content)
      {
        //In EditMode, unpublished or expired content is still returned
        if (GetContextMode() == ContextMode.Edit)
          {
            return true;
          }
        return base.ShouldContentBeExposed(content);
      }
    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;
      }
  }

 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 new class called CustomUrlResolverService that derived from UrlResolverService, and override the ResolveUrl method.
  • Register this new class as the default service for UrlResolverService in InitializableModule.

Example:

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;
      }
}

Example:

public void ConfigureContainer(ServiceConfigurationContext context)
  {
    context.Services.AddSingleton<UrlResolverService, CustomUrlResolverService>();
  }
public class CustomUrlResolverService : UrlResolverService
  {
    private readonly ServiceAccessor<HttpContextBase> _httpContextAccessor;
    public CustomUrlResolverService(IUrlResolver urlResolver, ServiceAccessor<HttpContextBase> httpContextAccessor) : base(urlResolver)
      {
        _httpContextAccessor = httpContextAccessor;
      }
    public override string ResolveUrl(ContentReference contentLink, string language)
      {
        return _urlResolver.GetUrl(contentLink, language, new UrlResolverArguments
          {
            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

By default, Content Delivery API filters content based on the visitor group of the current user. 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.

1210

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 new 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>());