In larger MVC projects, my group often has quite a few partial views in the Shared folder. Generally this leads to a lot of .cshtml files in the Shared folder, which tends to get a bit crowded:

Lots of partial views

Many of those partial views apply to multiple actions in a single controller. I would prefer to have a way to associate some of those partial views with the controller and views they are related to, while still allowing MVC to render them using @Html.Partial("PartialViewName").  We can do this by adding a new, custom ViewEngine to the MVC ViewEngine collection, which will point the engine at a new Partials folder inside each View subfolder.

It'll look like this:

public class SplitPartialsViewEngine : RazorViewEngine
{
    private static string[] NewPartialViewFormats = new[] { 
        "~/Views/{1}/Partials/{0}.cshtml",
        "~/Views/Shared/Partials/{0}.cshtml"
    };

    public SplitPartialsViewEngine()
    {
        base.PartialViewLocationFormats = base.PartialViewLocationFormats.Union(NewPartialViewFormats).ToArray();
    }
}

Those strings in NewPartialViewFormats specify the additional paths in which the engine is to look for partial views, and the {0} and {1} represent the action name and controller name, respectively.

The constructor for this engine UNIONs the new path templates with the existing ones, so that, in effect, we're just adding new locations for MVC to look for partial views. Basically, what we've told the engine is to look in a "Partials" folder under each Controller's View folder, and if the designated partial view is not there, look in the "Shared" folder.

But we're not done yet. We also need to tell MVC that we want to use this engine. Specifically, we need to add a line in the Global.asax file's Application_Start():

ViewEngines.Engines.Add(new SplitPartialsViewEngine());

Now we can eliminate much of the overcrowding of the Shared folder! Little changes like this make larger projects much easier to change and update, and more fun to work on.

The final thing you'd have to do is create a Partials folder beneath each Controller's Views' folder to hold the partials that are only used for that controller.

As always, you can grab a basic working sample project for this from GitHub. Pull requests welcome!

exceptionnotfound/CustomViewEngine
Contribute to exceptionnotfound/CustomViewEngine development by creating an account on GitHub.

Happy Coding!