Multiple views in different projects with same name

Dec 15, 2014 at 4:49 PM
I have the following basic project structure:
MySolution
    MyProjectA
        Controllers
            Course
                CourseController.cs
        Views
            Course
                GetCourse.cshtml
    MyProjectB
        Controllers
            Course
                CourseController.cs
        Views
            Course
                GetCourse.cshtml
    MyWebUIProject
Project A and Project B both have Course controllers and GetCourse views, however they work completely differently. I have RazorGenerator configured to serve razor pages from the two module projects through MyWebUIProject, and everything was working fine until I created two views with the same name in different projects.

Now when calling the Course controller in Project B, it is trying to return the GetCourse view in Project A. I've tried playing around with the baseVirtualPath, view location formats, nothing works. I don't want to have to use Areas or rename views, as splitting the modules of my application out into class libraries should be enough to differentiate them.

Is there a way to configure RazorGenerator to serve views via controllers only from the class library the controller is in?
Mar 16, 2015 at 12:30 AM
I am having this problem also. I am trying to use this for multi-tenancy where projectA is clientA and projectB is clientB, etc. It seems when registering view engines by scanning for assemblies these are added alphabetically - hence why projectA's (clientA's in my case) views are always returned. Did you find a solution to this?
Mar 16, 2015 at 12:39 AM
Edited Mar 16, 2015 at 12:41 AM
Hi Phil,

Yes, after trying just about everything I could think of I finally created a base Controller class, overrode the View methods, and within those methods cleared and reset the ViewEngine configuration each time View() is called so that only one PrecompiledMvcEngine object is registered at any one time. Along the way I had to preserve the other default ViewEngines that might also be registered. It seems to work, though my app is a small intranet application and I really have no idea if this approach will scale. Note that the PrecompiledMvcEngine for the specific module is passed to the base controller class in the constructor.
    public abstract class MyController : Controller {

        private static PrecompiledMvcEngine moduleEngine;

        protected MyController(PrecompiledMvcEngine engine) {
            moduleEngine = engine;
        }

        protected new ViewResult View(string view, object model) {
            ConfigureViewEngines();
            return base.View(view, model);
        }

        private static void ConfigureViewEngines() {
            var otherEngines = ViewEngines.Engines.Where(item => item.GetType() != typeof(PrecompiledMvcEngine)).ToList();
            ViewEngines.Engines.Clear();
            ViewEngines.Engines.Insert(0, moduleEngine);
            foreach(var engine in otherEngines)
                ViewEngines.Engines.Add(engine);
        }

}