Pages

Thursday, October 21, 2021

Moving the DisplayTemplates Folder

Optimizely uses DisplayTemplates to provide a way to render different partials for data types. DisplayTemplates are native to ASP.Net MVC, though, and Optimizely builds upon them, for instance, by specifying a Tag. An example of this is the rendering of ContentReference properties in my articles here and here. The MVC engine defaults the location for them to "Views/Shared/DisplayTemplates". Sometimes, though, it's convenient to reference different locations, and this is how you can do that. 

First, why would you want to do this?

There are a number of cases for organization purposes where you might want to change the DisplayTemplates location. I use a Feature folder approach to organize components across projects or in a single project, so all related items are together, including DisplayTemplates. This makes it easier to find things, it cleans up the default location, and it allows me to easily and completely remove components I don't need. 

In the example for this article, it's simply to move the Views structure up a level. I have never been fond of the "Views/Shared" folder approach, and prefer to organize things into Pages, Blocks, Layouts, DisplayTemplates, and PreviewTemplates folders. 

An example folder structure

To move the DisplayTemplates directory, override the FindPartialView method

If you don't already have a ViewEngine class defined, create one and inherit from RazorViewEngine. If you already have one, use the FindPartialView method below to override the base. 

[pre class="brush:csharp;class-name:collapse-box"]
using System;
using System.Linq;
using System.Web.Mvc;

namespace BaseEpiserverSite.Initialization
{
    public class ViewEngine : RazorViewEngine
    {
        public ViewEngine()
        {
            
        }
        public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
        {
            var pathParts = partialViewName.Split('/');
            if (string.Equals(pathParts.First() ?? "", "DisplayTemplates", StringComparison.CurrentCultureIgnoreCase))
            {
                var templatePath = string.Join("/", pathParts.Prepend("/Views")) + ".cshtml";
                if (base.FileExists(controllerContext, templatePath))
                {
                    return new ViewEngineResult(CreatePartialView(controllerContext, templatePath), this);
                }
            }
            return base.FindPartialView(controllerContext, partialViewName, useCache);
        }
    }
}
[/pre]

 

The path for DisplayTemplates always starts with the DisplayTemplate folder. This override checks for that path part, and prepends the Views folder directly to make the path "/Views/DisplayTemplates/[partialname].cshtml". If the file exists, it returns a new PartialView result from that path; if it doesn't it continues down the normal stack for finding the partial. 

Register the ViewEngine with an InitializationModule

If you didn't previously have a custom ViewEngine, and you created one just for this, make sure you register it with an InitializationModule for this to work. 

[pre class="brush:csharp;class-name:collapse-box"]
using EPiServer.Framework;
using EPiServer.Framework.Initialization;
using System.Web.Mvc;

namespace BaseEpiserverSite.Initialization
{
    [ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
    public class SiteInitialization : IInitializableModule
    {
        public void Initialize(InitializationEngine context)
        {
            ViewEngines.Engines.Insert(0, new ViewEngine());
        }

        public void Uninitialize(InitializationEngine context)
        {
        }
    }
}
[/pre]


Seeing it in action


No comments:

Post a Comment

Share your thoughts or ask questions...