5

I have an MVC project that requires there to be 2 different View folders. One is at ~/Views/ and one at ~/Framework/Views/. This is done by creating a custom view engine based on the razor view engine like this:

public class MyViewEngine : RazorViewEngine
{
    private static string[] AdditionalViewLocations = new[]{
        "~/Framework/Views/{1}/{0}.cshtml",
        "~/Framework/Views/{1}/{0}.vbhtml",
        "~/Framework/Views/Shared/{0}.cshtml",
        "~/Framework/Views/Shared/{0}.vbhtml"
    };

    public MyViewEngine()            
    {
        base.PartialViewLocationFormats = base.PartialViewLocationFormats.Union(AdditionalViewLocations).ToArray();
        base.ViewLocationFormats = base.ViewLocationFormats.Union(AdditionalViewLocations).ToArray();
        base.MasterLocationFormats = base.MasterLocationFormats.Union(AdditionalViewLocations).ToArray();
    }
}

The problem is that I want to use a different _ViewStart.cshtml file in each of the 2 Views folder (i.e. ~/Views/_ViewStart.cshtml for views found in the ~/Views/ folder and ~/Framework/Views/_ViewStart.cshtml for views found in the ~/Framework/Views/ Folder), however the View Engine just uses the first one it finds which is the original one in ~/Views/.

Is this possible to do?

Thank you

hofnarwillie
  • 3,563
  • 10
  • 49
  • 73
  • Why not use Areas instead of messing with view engine? – Nikola Radosavljević Mar 07 '13 at 23:00
  • 1
    This is definitely possible - in fact I just whipped it up on my machine using the view engine you supplied, just copied and pasted. I am not seeing the same behavior as you. I have two _ViewStart files, one at ~/Framework/Views/_ViewStart.cshtml, and one at ~/Views/_ViewStart.cshtml. When I run a view within ~/Framework/Views/, it uses the Framework _ViewStart. When I run a view within ~/Views/, it uses the _ViewStart there. Double checking the code in RazorViewEngine using DotPeek also confirms that this is how it should behave. Are you sure you aren't missing something? –  Mar 07 '13 at 23:32
  • 1
    @NickAceves: Thanks you're right. My file was saved in the wrong location and a duplicate of the wrong file was saved in the right location! What a dooch! Thanks again. (put it in an answer and I'll mark it) – hofnarwillie Mar 08 '13 at 09:55

2 Answers2

7

This is definitely possible, I think you just missed something.

I have tested this myself using the view engine you supplied (copied and pasted verbatim). I am not seeing the same behavior as you. I have two _ViewStart.cshtml files, one at ~/Framework/Views/_ViewStart.cshtml, and one at ~/Views/_ViewStart.cshtml.

When I run a view within ~/Framework/Views/, it uses the _ViewStart.cshtml in the Framework folder. When I run a view within ~/Views/, it uses the _ViewStart.cshtml in the Views folder.

Double checking the code in RazorViewEngine using DotPeek also confirms that this is exactly how it should behave. The view engine starts checking in for a file named _ViewStart.cshtml within the same folder as the view being rendered, and then walks up the directory tree until it gets to the root of the application.

3

The selection of _ViewStart is hierarchical, but you've added ~/Framework/Views parallel to ~/Views. I don't think Razor is set up to actually do what you want (i.e. two completely parallel view locations). If you were to put Framework into the main Views folder, your _ViewStarts would load properly, though.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • I see yes. So would the framework directory be something like this: `~/Views/Framework/_ViewStart.cshtml` and `~/Views/Framework/Controller/Action.cshtml`. And is the custom razor view engine then still needed but changing the AdditionalViewLocations to something like this: `"~/Views/Framework/{1}/{0}.cshtml"`? – hofnarwillie Mar 07 '13 at 22:38
  • Or is that still parallel view locations? Should I just add the Framework folder as an area? (Haven't used areas before, so sorry if I'm misunderstanding) – hofnarwillie Mar 07 '13 at 22:48
  • 1
    No, that's exactly what I'm talking about. If you put all your "Framework" views together in a folder and put a `_ViewStart` in that folder, then it will apply to everything at that level and below. Think of it as an override. You would no longer need a custom razor engine. – Chris Pratt Mar 08 '13 at 15:41
  • As for areas, that's a perfectly acceptable approach as well. Areas have their own `Views` folder, but they still look in the main `Views` folder as well. So you could have a "Framework" area, and put a `_ViewStart` in the `~/Areas/Framework/Views` folder. – Chris Pratt Mar 08 '13 at 15:43