Search code examples
c#asp.net-coreasp.net-core-viewcomponent

Cross area ViewComponents


I have a ViewComponent stored in an area named "Dashboard" but now I want to use this ViewComponent in another area called "Appplications". Yes I could add it to the root views/shared folder but I'm striving to make a very modular application through the strong contained use of areas.

ASP.NET 5 RC1 MVC 6 doesn't seem to support cross area references to other components.

How do I add additional view locations? I need to add: /Areas/Dashboard/Views/Shared/Components/DashboardMenu/Default.cshtml as a search location to the view renderer

InvalidOperationException: The view 'Components/DashboardMenu/Default' was not found. The following locations were searched:
/Areas/Applications/Views/Application/Components/DashboardMenu/Default.cshtml
/Areas/Applications/Views/Shared/Components/DashboardMenu/Default.cshtml
/Views/Shared/Components/DashboardMenu/Default.cshtml.

Solution

  • Worked it out...

    Startup.cs

    // Add additional razor view engine configuration to facilitate:
    // 1. Cross area view path searches
    services.Configure<RazorViewEngineOptions>(options =>
    {
        options.ViewLocationExpanders.Add(new RazorViewLocationExpander());
    });
    

    Then create a class called RazorViewLocationExpander.cs

    using Microsoft.AspNet.Mvc.Razor;
    using System.Collections.Generic;
    using System.Linq;
    
    public class RazorViewLocationExpander : IViewLocationExpander
    {
        public void PopulateValues(ViewLocationExpanderContext context) { }
    
        public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
        {
            List<string> locations = viewLocations.ToList();
    
            locations.Add("/Areas/dashboard/Views/Shared/{0}.cshtml");
    
            return locations;
        }
    }
    

    I would not recommend this generally. I am using this solution as a special case because I am using an area to isolate templating and core code for my other (members-only) areas to consume - so they need to know where to find this shared code. I am attempting to separate the public code from the admin code and this is the cleanest, most modular solution I can think of. The dashboard area will be present for all website that require members-only administration area. It is bending the rules of MVC ever so slightly.