<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Blog posts by Kristian Elmholt Kjær</title><link href="http://world.optimizely.com" /><updated>2018-05-19T12:31:00.0000000Z</updated><id>https://world.optimizely.com/blogs/kristian-elmholt-kjar/</id> <generator uri="http://world.optimizely.com" version="2.0">Optimizely World</generator> <entry><title>Custom View Locations for Pages, Blocks and more</title><link href="https://world.optimizely.com/blogs/kristian-elmholt-kjar/dates/2018/5/custom-view-locations-for-pages-blocks-and-more/" /><id>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h2&gt;Background&lt;/h2&gt;
&lt;p&gt;In a typical Episerver, or MVC Applicaton for that matter, the Views specified in a Controller are resolved by paths defined in the System.Web.Mvc.RazorViewEngine.&lt;/p&gt;
&lt;p&gt;The paths for Views are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;&quot;~/Views/{1}/{0}.cshtml&quot;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&quot;~/Views/Shared/{0}.cshtml&quot;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In Episerver Page Controllers, we need to specify an Index-method with the Page-type as method parameter, like this:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public class StartPageController : PageController&amp;lt;StartPage&amp;gt;
{
&amp;nbsp; &amp;nbsp; public ActionResult Index(StartPage currentPage)
&amp;nbsp; &amp;nbsp; {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return View(currentPage);
&amp;nbsp; &amp;nbsp; }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we take a look at the paths above, the name of the Controller (except -&quot;Controller&quot;) will be used at &quot;{1}&quot;, and the name of the Action is used at &quot;{0}&quot;, meaning default View path for our Controller above will be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;&quot;~/Views/StartPage/Index.cshtml&quot;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span&gt;Flooding of &quot;Index.cshtml&quot; files&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;If you like me, use ReSharper and namely the &quot;Navigation -&amp;gt; Search Everywhere/Go to Type&quot; function to navigate/find your Views files, the amount of Index.cshtml files you&#39;d end up - by default - becomes annoying. You probably already know this, but the files and folders in your Website project, will be something like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Views
&lt;ul&gt;
&lt;li&gt;StartPage
&lt;ul&gt;
&lt;li&gt;Index.cshtml&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;LandingPage
&lt;ul&gt;
&lt;li&gt;Index.cshtml&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CasePage
&lt;ul&gt;
&lt;li&gt;Index.cshtml&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ArticlePage
&lt;ul&gt;
&lt;li&gt;Index.cshtml&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Etc. etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thankfully, we can make up for that!&lt;/p&gt;
&lt;h2&gt;Creating a custom ViewEngine&lt;/h2&gt;
&lt;p&gt;Go ahead and create a new class that inherits System.Web.Mvc.RazorViewEngine. Like this:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public class EpiserverViewEngine : System.Web.Mvc.RazorViewEngine
{
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To define your own paths for Views (Pages and Catalog-nodes) and PartialViews (Blocks, Partials), add a constructor and set the value of ViewLocationFormats and PartialViewLocationFormats. Like this:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public class EpiserverViewEngine : System.Web.Mvc.RazorViewEngine
{
    public EpiserverViewEngine()
    {
        var partialViewLocations = new[]
        {
            &quot;~/Views/Blocks/{1}.cshtml&quot;,
            &quot;~/Views/Shared/{0}.cshtml&quot;,

            &quot;~/Views/Blocks/{1}/{0}.cshtml&quot;,
            &quot;~/Views/Shared/{1}/{0}.cshtml&quot;
        };

        var viewLocations = new[]
        {
            &quot;~/Views/Pages/{1}.cshtml&quot;,
            &quot;~/Views/Nodes/{1}.cshtml&quot;,
            &quot;~/Views/Catalog/{1}.cshtml&quot;,

            &quot;~/Views/Pages/{1}/{0}.cshtml&quot;,
            &quot;~/Views/Nodes/{1}/{0}.cshtml&quot;,
            &quot;~/Views/Catalog/{1}/{0}.cshtml&quot;
        };

        PartialViewLocationFormats = partialViewLocations;
        ViewLocationFormats = viewLocations;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above paths are the ones I use, and it gives much more flexibility.&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Potential problem&lt;/h3&gt;
&lt;p&gt;I&#39;ve seen other examples of this where the paths above, are all set to the ViewLocationFormats property - and that includes both Views and PartialViews. This results in Episerver/MVC potentially resolving PartialViews as regular Views. And as we know, a PartialView should not be rendered with a Layout, which also includes model inheriting being a requirement.&lt;/p&gt;
&lt;p&gt;I was trying to render a ContentArea in which I had inserted a Block of mine, and that resulted in an exception with the message:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The model item passed into the dictionary is of type &#39;EPiServer.Core.ContentArea&#39;, but this dictionary requires a model item of type &#39;Namespace.IPageViewModel&amp;lt;T&amp;gt;&#39;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It took me quite some time debugging why this became a problem suddenly. When it finally struck me, that the PartialView belonging to my Block was being resolved as a regular View. So talk about a eureka-experience!&lt;/p&gt;
&lt;h2&gt;Register your ViewEngine&lt;/h2&gt;
&lt;p&gt;To register your new EpiserverViewEngine, create an InitializationModule - like this:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[InitializableModule]
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class ViewEngineInitializationModule : IInitializableModule
{
    public void Initialize(InitializationEngine context)
    {
        System.Web.Mvc.ViewEngines.Engines.Add(new EpiserverViewEngine());
    }

    public void Uninitialize(InitializationEngine context) {}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You are now ready to use it. You can leave your StartPageController (example above), and use paths like these instead:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Views/
&lt;ul&gt;
&lt;li&gt;Pages/
&lt;ul&gt;
&lt;li&gt;StartPage.cshtml&lt;/li&gt;
&lt;li&gt;LandingPage.cshtml&lt;/li&gt;
&lt;li&gt;CasePage.cshtml&lt;/li&gt;
&lt;li&gt;ArticlePage/ &lt;em&gt;(Folder to bundle stuff together)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;Index.cshtml&lt;/li&gt;
&lt;li&gt;_MyArticlePagePartial.cshtml&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Blocks/
&lt;ul&gt;
&lt;li&gt;NewsletterBlock.cshtml&lt;/li&gt;
&lt;li&gt;TeaserBlock.cshtml&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Feel free to use this, modify it and happy coding!&lt;/p&gt;
&lt;p&gt;/Kristian&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</id><updated>2018-05-19T12:31:00.0000000Z</updated><summary type="html">Blog post</summary></entry></feed>