Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Stephen 22 posts 144 karma points
    Mar 22, 2022 @ 02:42
    Stephen
    0

    Change Razor View Location Order in Umbraco 9

    I'm looking for guidance on how to change the Razor view location order in an Umbraco 9.3 solution.

    My goal is to have the web application prioritise .cshtml view files located in the ~/Foo/ directory. So far, I've only been able to add this folder to the end of the view location order.

    Startup.cs

    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Mvc.Razor;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    using Umbraco.Cms.Core.DependencyInjection;
    using Umbraco.Extensions;
    
    namespace Umbraco.Templates.Site
    {
        public class Startup
        {
            private readonly IWebHostEnvironment _env;
            private readonly IConfiguration _config;
    
            public Startup(IWebHostEnvironment webHostEnvironment, IConfiguration config)
            {
                _env = webHostEnvironment;
                _config = config;
            }
    
            public void ConfigureServices(IServiceCollection services)
            {
                // Configure the custom view location order
                services.ConfigureOptions<CustomRenderRazorViewEngineOptionsSetup>();
    
                services.AddUmbraco(_env, _config)
                    .AddBackOffice()
                    .AddWebsite()
                    .AddComposers()
                    .Build();
            }
    
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
    
                app.UseUmbraco()
                    .WithMiddleware(u =>
                    {
                        u.UseBackOffice();
                        u.UseWebsite();
                    })
                    .WithEndpoints(u =>
                    {
                        u.UseInstallerEndpoints();
                        u.UseBackOfficeEndpoints();
                        u.UseWebsiteEndpoints();
                    });
            }
        }
    }
    

    CustomRenderRazorViewEngineOptionsSetup.cs

    Based on Umbraco's own RenderRazorViewEngineOptionsSetup.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.AspNetCore.Mvc.Razor;
    using Microsoft.Extensions.Options;
    
    namespace Umbraco.Templates.Site
    {
        /// <summary>
        /// Configure view engine locations for front-end rendering
        /// </summary>
        public class RenderRazorViewEngineOptionsSetup : IConfigureOptions<RazorViewEngineOptions>
        {
            /// <inheritdoc/>
            public void Configure(RazorViewEngineOptions options)
            {
                if (options == null)
                {
                    throw new ArgumentNullException(nameof(options));
                }
    
                options.ViewLocationExpanders.Add(new ViewLocationExpander());
            }
    
            /// <summary>
            /// Expands the default view locations
            /// </summary>
            private class ViewLocationExpander : IViewLocationExpander
            {
                public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
                {
                    string[] umbViewLocations = new string[]
                    {
                        "/Foo/Views/{0}.cshtml",
                        "/Foo/Views/Shared/{0}.cshtml",
                        "/Foo/Views/Partials/{0}.cshtml",
                        "/Foo/Views/MacroPartials/{0}.cshtml",
                    };
    
                    viewLocations = umbViewLocations.Concat(viewLocations);
    
                    return viewLocations;
                }
    
                // not a dynamic expander
                public void PopulateValues(ViewLocationExpanderContext context) { }
            }
        }
    }
    

    This results in the following view location order, with the default Umbraco view locations taking priority:

    1. /App_Plugins/Views/
    2. /App_Plugins/Views/Shared
    3. /App_Plugins/Views/Partials/
    4. /App_Plugins/Views/MacroPartials/
    5. /Views/
    6. /Views/Shared/
    7. /Views/Partials/
    8. /Views/MacroPartials/
    9. /Foo/Views/
    10. /Foo/Views/Shared/
    11. /Foo/Views/Partials/
    12. /Foo/Views/MacroPartials/

    How can I get the four ~/Foo/ items to the top of the list of view locations?

  • Stephen 22 posts 144 karma points
    Mar 23, 2022 @ 19:09
    Stephen
    0

    Other things I've tried:

    • Using services.Configure() instead of services.ConfigureOptions().
    • Performing the customisation after services.AddUmbraco() ... .Build(); instead of before.

    Any idea as to how I could gain more control over the view location order?

  • DG 8 posts 119 karma points
    Apr 28, 2022 @ 15:33
    DG
    100

    I had this same problem. Check this github issue for a solution: https://github.com/umbraco/Umbraco-CMS/issues/12157

    Essentially you'll want to override the default razor view engine replacing it with one which adds your custom view expanders before the umbraco ones.

  • Stephen 22 posts 144 karma points
    May 02, 2022 @ 02:39
    Stephen
    1

    This is exactly what I was looking for, thank you for sharing!

Please Sign in or register to post replies

Write your reply to:

Draft