Good Good Not Great

Some sort of a decision procedure

Previewing custom document types in Episerver

15 Sep 2018 | Estimated read time about 5 minutes

Categories: (Episerver) (How to)

Recently I worked on a project where we needed to enable "edit mode" preview for a custom document type. It seemed like it would be a trivial task, just set up a view and map the document type in the TemplateCoordinator. After debugging a bit it turns out this would not be the case.

Thanks to Ben McKernan on the Episerver forums for providing some insights, specifically that MediaData does not have on-page edit as an available view, which is why we wouldn't be able to hit the controller even if we set one up ourselves. We would either need to extend VideoData or ImageData (not possible in our case) or create a UIDescriptor for our document type. Fortunately creating UIDescriptors are very straightforward.

First, this is our custom Document Type DocumentFile.cs that extends MediaData.

using EPiServer.Core;
using EPiServer.DataAbstraction;
using EPiServer.DataAnnotations;
using EPiServer.Framework.DataAnnotations;
using EPiServer.Web;
using System.ComponentModel.DataAnnotations;

namespace GoodGoodNotGreat.Sample.Models.Media
{
    [ContentType(DisplayName = "Document File", GUID = "003b5851-e153-41c5-b7d6-0f0d51da5bfa", Description = "Some custom document type we use a lot")]
    [MediaDescriptor(ExtensionString = "pdf")]
    public class DocumentFile : MediaData
    {        
        [Editable(true)]
        [Display(
            Name = "Title",
            GroupName = SystemTabNames.Content,
            Order = 10)]
        public virtual string Title { get; set; }
        
        // edited for brevity
        
        [UIHint(UIHint.Image)]
        [Editable(true)]
        [Display(
            Name = "Cover Image",
            GroupName = SystemTabNames.Content,
            Order = 100)]
        public virtual ContentReference CoverImage { get; set; }
    }
}

Next we need to create the UIDescriptor in DocumentDescriptor.cs

using GoodGoodNotGreat.Sample.Models.Media;
using EPiServer.Shell;

namespace GoodGoodNotGreat.Sample.Business.UIDescriptors
{
	[UIDescriptorRegistration]
	public class DocumentFileDescriptor : UIDescriptor<DocumentFile>
	{
		public DocumentFileDescriptor() : base("epi-iconObjectPage")
		{
			//let's not have edit mode be disabled
			DisabledViews = new string[] { };
			
			//and set the default to preview mode
			DefaultView = CmsViewNames.PreviewView;
		}
	}
}

We decided to go with implementing a controller for the document type as there would likely be extra feature requests now that on-page edit mode is available and our document type has additional required properties to hook up to a fancy Asset Library. It really is important to make the experience for editors as streamlined as possible.

Setting up the MediaPreviewController.cs

using System.Web.Mvc;
using GoodGoodNotGreat.Sample.Models.Media;
using EPiServer.Core;
using EPiServer.Framework.DataAnnotations;
using EPiServer.Framework.Web;
using EPiServer.Web;
using EPiServer.Web.Mvc;

namespace GoodGoodNotGreat.Sample.Controllers.Media
{
	[TemplateDescriptor(
		Inherited = false,
		TemplateTypeCategory = TemplateTypeCategories.MvcController,
		Tags = new[] { RenderingTags.Preview, RenderingTags.Edit },        
		AvailableWithoutTag = false,
		ModelType = typeof(DocumentFile))]
	//Note that if AvailableWithoutTag is true the same view will be used to view the actual
	//document when its public URL is hit. We don't want that here
	public class DocumentPreviewController : Controller, IRenderTemplate<DocumentFile>
	{
		//Change the action to receive you full document type model if you need
		//extra functionality
		//e.g. ActionResult Index(DocumentFile currentContent)
		public ActionResult Index(IContent currentContent)
		{			
			return View("~/Views/Shared/Media/DocumentPreview.cshtml", currentContent);
		}
	}
}

The last thing left would be to setup the DocumentPreview.cshtml view

@using EPiServer.Web
@using EPiServer.Web.Routing
@model EPiServer.Core.IContent

@{
	//We use a custom preview Layout for pages and blocks, we won't need that here
	Layout = null;

	//You should do this in the controller if you need more functionality
	//also note we don't supply a culture as this site is single culture
	var url = UrlResolver.Current.GetUrl(Model.ContentLink, "", new VirtualPathArguments { ContextMode = ContextMode.Default });
}

<object data="@url" type="application/pdf" width="100%" height="95%">
    <embed src="@url" type="application/pdf">
        <p>This browser does not support PDFs. Please download the PDF to view it: <a href="@url">Download PDF</a>.</p>
    </embed>
</object>

And that is all you need to get custom document types showing previews in Episerver CMS (this project is on v11).

Thanks for stopping by.

Recommended Posts