Reputation: 30499
Important Update
Since the release of MVC 2.0 Preview 1 this feature has been implemented as the part of the actual framework itself in the form of Areas. More details available on Phil Haack's blog here
I have a controller called ListManagerController. This controller contain an ActionResult method called Index(). When I right cick on Index in Visual Studio and select Add View the new view is created in /Views/ListManager/Index.
However I want the Index view and all subsequent views to be created in /Views/Manage/ListManager/. How would I accomplish this?
Edit: It was pointed out that this question is a duplicate of the question posted here. It seems my searching skills failed me initially.
Upvotes: 0
Views: 3612
Reputation: 16651
I know you already accepted an answer but here's what I came up with while experimenting with the same idea, with the help of Phil Haack's post.
First you need to have your own ViewEngine to look for folders under View folder. Something like this : (You'll notice that it looks a lot like Phil Haack's areas code)
public class TestViewEngine : WebFormViewEngine
{
public TestViewEngine()
: base()
{
MasterLocationFormats = new[] {
"~/Views/{1}/{0}.master",
"~/Views/Shared/{0}.master"
};
ViewLocationFormats = new[] {
"~/{0}.aspx",
"~/{0}.ascx",
"~/Views/{1}/{0}.aspx",
"~/Views/{1}/{0}.ascx",
"~/Views/Shared/{0}.aspx",
"~/Views/Shared/{0}.ascx"
};
PartialViewLocationFormats = ViewLocationFormats;
}
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
ViewEngineResult rootResult = null;
//if the route data has a root value defined when mapping routes in global.asax
if (controllerContext.RouteData.Values.ContainsKey("root")) {
//then try to find the view in the folder name defined in that route
string rootViewName = FormatViewName(controllerContext, viewName);
rootResult = base.FindView(controllerContext, rootViewName, masterName, useCache);
if (rootResult != null && rootResult.View != null) {
return rootResult;
}
//same if it's a shared view
string sharedRootViewName = FormatSharedViewName(controllerContext, viewName);
rootResult = base.FindView(controllerContext, sharedRootViewName, masterName, useCache);
if (rootResult != null && rootResult.View != null) {
return rootResult;
}
}
//if not let the base handle it
return base.FindView(controllerContext, viewName, masterName, useCache);
}
private static string FormatViewName(ControllerContext controllerContext, string viewName) {
string controllerName = controllerContext.RouteData.GetRequiredString("controller");
string root = controllerContext.RouteData.Values["root"].ToString();
return "Views/" + root + "/" + controllerName + "/" + viewName;
}
private static string FormatSharedViewName(ControllerContext controllerContext, string viewName) {
string root = controllerContext.RouteData.Values["root"].ToString();
return "Views/" + root + "/Shared/" + viewName;
}
}
Then in your Global.asax
replace the default ViewEngine with your custom one, on Application_Start
:
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new TestViewEngine());
Now when you are defining routes in Global.asax
, you need to set a root
value indicating the folder to look for under the View folders like so :
routes.MapRoute(
"ListManager",
"ListManager/{action}/{id}",
new { controller = "ListManager", action = "Index", id = "", root = "Manage" }
);
Upvotes: 1
Reputation: 602
This question is VERY much a repeat of this question
so I'll quote my answer to that one here.
I came up with a different solution that didn't require me to roll my own view engine.
Basically, I wanted to keep MVC as "Convention" driven as possible, but I still wanted to organize all of my "Admin" views under the ~/Views/Admin folder.
Example:
- ~/Views/Admin/User/
- ~/Views/Admin/News/
- ~/Views/Admin/Blog/
My solution was to create a new base class for my specific admin controllers and "force" the path to the view for that controller.
I have a blog post and sample code here: Organize your views in ASP.Net MVC
Upvotes: 0
Reputation: 14479
The location of views is tied to the ViewFactory you are using. AFAIK the web forms view engines does not support areas [Manage in your example].
Spark supports this and is very clean, you can also mix and match web forms and spark views so you don't have to recreate all your views.
UPDATE: Looks like Phil Haack has a blog post on how to achieve this. His code is for the RC, but I think that should compile fine against ASP.NET MVC RTM.
Upvotes: 3