Managing Cumbersome Shared Views Folder for Large Projects in MVC

While ASP.NET MVC promotes clean separation-of-concerns for your web applications, there are some short comings. A problem you’ll run into on large ASP.NET MVC projects is the Views section of your web application becomes completely crowded with hundreds or thousands of files.

Usually, these view files are organized into sections by controller which keeps this manageable. For example, your solution might look like:

  • Controllers
  • Models
  • Views
    • Home
      • Index.cshtml
      • About.cshtml
    • Products
      • All.cshtml
      • Show.cshtml
      • New.cshtml
    • Shared
    • etc…

So that any one folder might only have 10 cshtml files. But there is one folder that is disproportionately crowed, that Shared folder where all the common partial views and layouts are kept. A quick look at one of my recent MVC projects shows 113 files in that shared folder!

A 113 files tossed into a single folder is painful to manage and difficult to find what you’re looking for at a glance. If they could be categorized into subfolders, say things like Shared/Navigation, Shared/Accounts, Shared/Users, things would be good again.

Presently MVC doesn’t look into subfolders of the shared views folder. But with a little open-source library I wrote and a few clicks on NuGet, it will!

Introducing Enhanced View Locations for MVC

To address this issue, I’ve created a project over at GitHub (recently moved from CodePlex):

       Enhanced View Locations for MVC
       https://github.com/mikeckennedy/enhanced_aspnet_mvc_views

With this library added to your project (via NuGet), your massive Shared folder can look like this:

Here’s how you use it (from the codeplex project documentation):

Enhanced View Locations for MVC allows you to further organize your ASP.NET MVC views without your action methods or Html.RenderPartial / Html.RenderAction elements knowing or caring about how they are organized or re-organized.

1. Begin by adding a reference to EnhancedViewLocations.dll to your ASP.NET MVC project via NuGet (http://nuget.org/List/Packages/EnhancedViewLocations) or by directly downloading and referencing it.

2. Next, define and register custom view locations in the form partial Uri’s from within the Global.asax file:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    RegisterGlobalFilters( GlobalFilters.Filters );
    RegisterRoutes( RouteTable.Routes );

    // Register the extra locations for views.
    RegisterCustomViewLocations();
}

private static void RegisterCustomViewLocations()
{
   // We can optionally enable the standard Razor view CS
   // (or VB) locations so we don't always search our
   // extra / custom areas first when searching for a view.
   // EnhancedViewLocator.EnableStandardRazorCSLocations();

   // Next, add two extra locations to store / arrange our views.

   // 1. in the templates folder under the standard shared view
   // folder.
   EnhancedViewLocator.AddFolder( "views/shared/templates" );

   // 2. in the navigation folder under the standard
   // shared view folder.
   EnhancedViewLocator.AddFolder( "views/shared/navigation" );

   // Finally, have the locator install a custom view
   // engine to manage the lookups.
   EnhancedViewLocator.Install( ControllerBuilder.Current );
}
Now you can create the to subfolders templates and navigation in the shared views (it can actually be any folder on your site provided you register it but I recommend keeping inside the views folder).
Hope you find it useful!
Cheers,

Michael Kennedy

A Python enthusiast and an entrepreneur. Host of Talk Python and Python Bytes podcasts, founder of Talk Python Training. Python Software Foundation Fellow.

6 comments

  • Manually adding other folders is okay (but tedious) – we can assume any sub folder of shared is to be checked. Maybe you can update the code to always add those subs when it starts.

  • I was hoping this would work for the shared DisplayTemplates and EditorTemplates folders as well. For me it’s mainly those folders that seem to get bloated. Sadly I can’t get it to work. I tried putting a DisplayTemplate subfolder in the registered folder, and I tried registering the custom DisplayTempate folder itself. A quick look at the source code makes me think this is not supported. Sadly I’m under quite a bit of time pressure in my current project or I would gladly take this on myself.

  • I have two Edit views, one is located in a controller folder (Views/Client/Edit.cshtml). I put the other one in a shared subfolder (Views/Shared/Document/Edit.cshtml) because it is used by two different controllers, and I use your library to have MVC search this folder, as described in your article. And this works fine. Except that now, when the Client/Edit action is invoked, the view found is not the one located in the controller folder, but the second one. And since the two views are mapped to different viewmodels, my application crashes. MVC’s default search behavior is to look in the controller’s folder first, then in the shared folder. Short of renaming one of the views, is there a way around this problem?

  • Recursive adding subfolders can be done this way :

        private void RegisterCustomViewLocations()
        {
            EnhancedViewLocator.EnableStandardRazorCSLocations();
            AddSubDirectories(Server.MapPath("~"), Server.MapPath("~/Views/Shared"));
            // Finally, have the locator install a custom view engine to manage the lookups.
            EnhancedViewLocator.Install(ControllerBuilder.Current);
        }
        private void AddSubDirectories(String Root, String Dir)
        {
            foreach (var item in Directory.GetDirectories( Dir) )
            {
                AddSubDirectories(Root, item);
                EnhancedViewLocator.AddFolder( item.Replace(Root, "").Replace(@"\",@"/") );
            }
        }
    

Submit a comment