Craig
Craig

Reputation: 36816

ASP MVC Folder Hierarchy

I have a fairly large ASP MVC application. Instead of having many controllers all in the controller directory I would rather create some hierarchy. So I might have something like

~\Controllers\Security\
~\Controllers\Maintenance\
~\Controllers\Reports\

I would also like to be able to do similar with Views

~\Views\Security\Users\
~\Views\Security\Roles\
~\Views\Maintenance\Customer\
~\Views\Maintenance\Product\

Is this easily done?

Upvotes: 3

Views: 1519

Answers (5)

mr0zek
mr0zek

Reputation: 73

Have you considered to switch to Features Folder. I've tried it (with little modifications) and it works pretty good.

Described in this post http://timgthomas.com/2013/10/feature-folders-in-asp-net-mvc/

Code examples are in Jimmiy Bogard's repo https://github.com/jbogard/presentations/tree/master/putyourcontrollersonadietv2

Upvotes: 1

Dan Malcolm
Dan Malcolm

Reputation: 4432

What you really want here is for your Views folder hierarchy to match the namespace hierarchy of your controllers. You can write a custom ViewEngine to do this fairly easily - see my ControllerPathViewEngine project on GitHub for details.

I've included a snippet of the ControllerPathRazorViewEngine class to outline how it works. By intercepting the FindView / FindPartialView methods and replacing the controller name with a folder path (based on controller namespace and name), we can get it to load views from nested folders within the main Views folder.

    public class ControllerPathRazorViewEngine : RazorViewEngine
    {
        //... constructors etc.

        public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
        {
            return FindUsingControllerPath(controllerContext, () => base.FindView(controllerContext, viewName, masterName, useCache));
        }

        public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
        {
            return FindUsingControllerPath(controllerContext, () => base.FindPartialView(controllerContext, partialViewName, useCache));
        }

        private ViewEngineResult FindUsingControllerPath(ControllerContext controllerContext, Func<ViewEngineResult> func)
        {
            string controllerName = controllerContext.RouteData.GetRequiredString("controller");
            string controllerPath = controllerPathResolver.GetPath(controllerContext.Controller.GetType());
            controllerContext.RouteData.Values["controller"] = controllerPath;
            var result = func();
            controllerContext.RouteData.Values["controller"] = controllerName;
            return result;
        }
    }

Upvotes: 0

Portman
Portman

Reputation: 31975

The concept you're searching for is called "areas", as outlined by Phil Haack here: http://haacked.com/archive/2008/11/04/areas-in-aspnetmvc.aspx

Upvotes: 2

antonioh
antonioh

Reputation: 2944

I think you're looking for something like what the "master" says in this post:

http://haacked.com/archive/0001/01/01/areas-in-aspnetmvc.aspx

Basically you have to create a ViewEngine to specify where to look for the views. It's a fairly simple code, just don't forget to register it in the global.asax! As for the controller part you'll have to register new routes also in the global.asax.

Upvotes: 4

ChadT
ChadT

Reputation: 7693

I would think you'd need to write your own RouteHandler, which shouldn't be too tough.

A quick google search turned up: This blog post detailing it

Upvotes: 1

Related Questions