Search code examples
c#asp.netasp.net-mvcmodel-view-controllerrazorengine

ASP Net Core View Location issue


I have been trying to create an MVC app in ASP.Net Core 1.0 and want my controller to use *cshtml files from a non-standard directory, say "View1".

This is the error I see when I tried to supply a location to the View method.

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
  Request starting HTTP/1.1 GET http://127.0.0.1:8080/  
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
  Executing action method
com.wormhole.admin.Controllers.HomeController.Index (wormhole) with arguments ((null)) - ModelState is Valid
fail: Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.ViewResultExecutor[3]
  The view 'View1/Home/Index.cshtml' was not found. Searched locations: /Views/Home/Index.cshtml
fail: Microsoft.AspNetCore.Server.Kestrel[13]
  Connection id "0HL1GIEMCQK67": An unhandled exception was thrown by the application.
System.InvalidOperationException: The view 'View1/Home/Index.cshtml' was not found. The following locations were searched:
/Views/Home/Index.cshtml

Is there a way that I can do this with ease and remove the old View locations from the app??

FYI. I have explored the options of using Areas, but that does not fit well into what I want from the App.


Solution

  • The solution is on this blog post

    You can use the IViewLocationExpander interface to define where to search the views

    public class MyViewLocationExpander : IViewLocationExpander
    {
        public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
        {
            yield return "/View1/{1}/{0}.cshtml";
            yield return "/View1/Shared/{0}.cshtml";
        }
    
        public void PopulateValues(ViewLocationExpanderContext context)
        {            
        }
    }
    

    The {1} is the controller name, and {0} is the view name. You can send a list of locations to search, and you can change the locations depending on the context.

    You need to register this class in the Startup.cs :

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.Configure<RazorViewEngineOptions>(options => {
                options.ViewLocationExpanders.Add(new MyViewLocationExpander());
            });
        }