1
votes

I have an older ASP.NET MVC application that uses classic web forms views. As an experiment, we've started to mix in some razor views. Unfortunately, the default precedence for where to find the desired view isn't what I want. MVC first looks in your /Views/ControllerName folder for aspx and ascx files. Then it moves to your /Views/Shared for aspx and ascx files. Then it starts over looking for .cshtml and .vbhtml files. What I want is for it not to go into the Shared folder until it's exhausted all the possibilities in the /Views/ControllerName folder. How do I do this?

--- UPDATE ---

Here's some additional information that might help explain what I'm after. By default, I get this search order:

~/Views/Home/Index.aspx
~/Views/Home/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
~/Views/Home/Index.cshtml
~/Views/Home/Index.vbhtml
~/Views/Shared/Index.cshtml
~/Views/Shared/Index.vbhtml 

What I want is this:

~/Views/Home/Index.aspx
~/Views/Home/Index.ascx
~/Views/Home/Index.cshtml
~/Views/Home/Index.vbhtml
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
~/Views/Shared/Index.cshtml
~/Views/Shared/Index.vbhtml

In other words, it shouldn't search Shared before it searches the /Views/ControllerName folder completely.

2

2 Answers

3
votes

You can configure the precedence of view engines in your global.asax.cs file

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);

        ViewEngines.Engines.Clear();
        ViewEngines.Engines.Add(new RazorViewEngine());
        ViewEngines.Engines.Add(new WebFormViewEngine());
    }
0
votes

After toying with it a bit, I was able to achieve what I wanted with a simple Fluent API. The extension methods remove the search locations I didn't want from each of the view engines. The search locations are stored in .ViewLocationFormats and .PartialViewLocationFormats string arrays. So here's the fluent API that removes the unwanted items from those arrays:

public static class BuildManagerViewEngineFluentExtensions {
    public static BuildManagerViewEngine ControllerViews(this BuildManagerViewEngine engine) {
        return FilterViewLocations(engine, x => x.Contains("/Views/Shared/") == false);
    }

    public static BuildManagerViewEngine SharedViews(this BuildManagerViewEngine engine) {
        return FilterViewLocations(engine, x => x.Contains("/Views/Shared/") == true);
    }

    private static BuildManagerViewEngine FilterViewLocations(BuildManagerViewEngine engine, Func<string, bool> whereClause) {
        engine.ViewLocationFormats = engine.ViewLocationFormats.Where(whereClause).ToArray();
        engine.PartialViewLocationFormats = engine.PartialViewLocationFormats.Where(whereClause).ToArray();
        return engine;
    }
}

And then, in my global.asax, I added the following lines to protected void Application_Start()

ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new RazorViewEngine().ControllerViews());
ViewEngines.Engines.Add(new WebFormViewEngine().ControllerViews());
ViewEngines.Engines.Add(new RazorViewEngine().SharedViews());
ViewEngines.Engines.Add(new WebFormViewEngine().SharedViews());