.net MVC Areas and subfolders - asp.net-mvc

I am using Areas in my project but I would like to organise my views within these areas into sub folders.
For example, I have an area called Members which contains a Controller called Settings and another Controller called MemberCategory. MemberCategory is in effect a subfolder of Settings.
I would like when I access the Member Category view for my url to resolve to Members/Settings/MemberCategory
At present it resolves to Members/MemberCategory
Is it possible to nest the views into subfolders and change the controller to point to
return View("Members/Settings/MemberCategory");
Or do this need to done with routing?
Any examples would be appreciated.

I have resolved this problem with Routes and not nesting the views into subfolders.
In my Area Registration file I have added the following above the default route:
context.MapRoute(
"MemberCategory",
"Members/Settings/MemberCategory",
new { controller = "MemberCategory", action = "Index" }
);
context.MapRoute(
"MemberCategoryAction",
"Members/Settings/MemberCategory/{action}/{id}",
new { controller = "MemberCategory", action = "Index", id = UrlParameter.Optional }
);
Not sure if this is the most elegant way of doing this but it works in my case.

You can also do something like:
return this.View("../MailTemplates/ResetPassword");
To get to the view you want to use. The code editor will not be able to resolve this, but it works.
I think this is cleaner than:
return this.View("~/Areas/Cms/MailTemplates/ResetPassword");

Related

How to implement my own folder structure(architecture) in ASP.NET MVC Project?

As we know, when we create an MVC application, it creates its own typical structure which is known as convention over configuration and its a good practice .
It configure views, controller and model separately .
My concern is, can i architect(design) it like :
If I do that, My viewengine will search views inside view not inside subfolders and there are so many things like routing will get changed.. and so on..
Actually I dont want to construct my view,controller or model in a typical way, I want to put my view separately according to my domain, not according to controller like MVC does.
However in case of controller we can use any folder structure . I am specific about model,views and routing should not be affected as well.
And it is all about "Convention over My own Configuration".
Can someone please explain, how to get it done or any other alternatives.
Thanx
Anupam.
It sounds like what you are looking for is 'Areas'. This allows you to separate your controllers & views into separate 'area' folders.
More information can be found here, as including the necessary information to get this set up in this answer is probably not practical:
http://msdn.microsoft.com/en-GB/library/ee671793(v=vs.100).aspx
The location and folder structure of your controllers and models doesn't really matter, should work either way. Controllers are located by their type and classname.
The viewengine by default does search subfolders, trying to match with the naming of your controller. It searches multiple locations.
Now, if you want to change how the view engine searches for files you can configure it in global.asax. Have a look here regarding RazorViewEngine for example.
Personally I have gone away from the view engine auto locating my views and instead use relative paths for all of them because I think it makes it more readable overall.
Below is an example of a configured view engine and a relative path.
global.asax
ViewEngines.Engines.Clear();
var razorEngine = new RazorViewEngine() { FileExtensions = new string[] { "cshtml" } };
ViewEngines.Engines.Add(razorEngine);
controller action
return View("~/Views/Home/Index.cshtml", model);
Hope I understood your question correctly.
So far I have reached to conclusion.
The thing we have to consider for this are :
1.Need to override ControllerFactory : we have to search controller in specific location or assembly reference.(by default controller factory just chak the controller name )
2.Need to override ViewEngine : We have to change view search location according to our need.
3.Little modification in Route : we have to specify module name in routs for proper redirection.
route will be something like :
routes.MapRoute(
name: "Default",
url: "{module}/{controller}/{action}/{id}",
defaults: new { module = "HR", controller = "Home", action = "Index", id = UrlParameter.Optional }
);
will implement it soon. Your suggestions are most welcome.

Nesting areas in asp.net mvc 3

I'm having trouble getting nested areas to work.
I would like to use a structure within the Areas folder, to organize my areas. I.e.:
Areas
Admin
Index (Default)
Locations
Controllers
Models
Views
...
Applications
Index (Default)
Calendar
Controllers
Models
Views
...
...
How do I go about structuring that with routes and how do I register each area. "Admin" and "Applications" are what I would call sections, and then the actual areas are located within a section.
I would have preferred using a route with an extra element, section, like so:
routes.MapRoute(
"Applications_default",
"{section}/{area}/{controller}/{action}/{id}",
new { section = "Applications", area = "Index", action = "Index", controller = "Home", id = UrlParameter.Optional }
);
Would that be possible?
I think I'm missing something with routes, because adding the route is one thing, but what would I name the area (AreaName property)? "Admin/Index"? "Admin.Index"? "Index" could be used in other places..
For now I'm trying the "normal" area registration using:
public override void RegisterArea(AreaRegistrationContext context) {
context.MapRoute(
"Admin_Index_default",
"Admin/Index/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
But when I go to http://localhost:60864/Admin/Index/Home/Index I get an error saying: "The resource cannot be found." :(
How do I structure my routes to comply with my desired tree structure?
I looked at another question: Can I nest areas in ASP.NET MVC?, but it did not solve my problem :(
Any help and guidance would be appreciated!
Thanks in advance
You should not restructure or reorganize your Areas folder. Keep the default, where each area has a Controllers, Models, and Views folder (plus AreaRegistration.cs, etc). Otherwise, you may be dealing with a spiderweb of namespace problems. Also, you will have to tell the razor engine which folders to check to find your views. Trust me your life will be happier if you just follow the conventions when it comes to areas.
If you want to create a deep URL structure, do it with routes. Your routes can be completely independent of your folder structure in MVC (unlike in webforms).
Do you try this route with a fresh MVC project? Meaning, no re-arrangement of the Areas folders? It should work, as long as your Admin area has a HomeController with an Index action:
public override void RegisterArea(AreaRegistrationContext context) {
context.MapRoute(
"Admin_Index_default",
"Admin/Index/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
I don't think this is supported. For deep URLs I suggest using MvcCodeRouting, and you can forget about routing issues.

Avoiding the Controller with Routing Rules in ASP.NET MVC

I've created a website with ASP.NET MVC. I have a number of static pages that I am currently serving through a single controller called Home. This creates some rather ugly URLs.
example.com/Home/About
example.com/Home/ContactUs
example.com/Home/Features
You get the idea. I'd rather not have to create a controller for each one of these as the actions simply call the View with no model being passed in.
Is there a way to write a routing rule that will remove the controller from the URL? I'd like it to look like:
example.com/About
example.com/ContactUs
example.com/Features
If not, how is this situation normally handled? I imagine I'm not the first person to run in to this.
Here's what I've done previously, using a constraint to make sure the shortcuts don't conflict with other routing rules:
routes.MapRoute(
"HomeShortcuts",
"{action}",
new { controller = "Home", action = "Index" },
new { action = "Index|About|ContactUs|Features" }
);
Add defaults for the controller names in the new statement. You don't have to have {controller} in the url.

organizing admin related controllers and viewpages

admin section is at www.example.com/admin
so I have an admincontroller.
But I also have user admin related controllers, and configuration controllers, I want the url to be like:
www.example.com/admin -> adminController
www.example.com/admin/user/ -> adminUserController
www.example.com/admin/user/edit
www.example.com/admin/user/add
I hate the name AdminUserController, any suggestions?
View pages are organized like:
/views/admin
/views/admin/user/
so in just manually reference the view page like return View("~/views/admin/user/add");
What other options do I have?
You can use multiple areas in the same project (in MVC 2). You could have an admin area. This lets you organize all the controllers in a sensible way, and fixes the naming issue: You'd have a "UserController" in the "Admin" area.
There is no direct relation between the Controller/Views Name and physical location and your Route, you can control this in the Global.asax, If you have an AdminController you can define a Route like
example.com/Admin/Manage/
In your Global will be like :
routes.MapRoute(
"AdminSection",
"Admin/Manage/{action}/{id}",
new { controller = "AdminController", action = "Index", id = "" }
);
So when a Route like this example.com/Admin/Manage/ is entered you redirect to the desired controller and action, the name of the controller is not strictly the one on the route.
Hope it Helps.

ASP.Net MVC View Architecture

Can the folders within the View have subfolders? if so, how does the Controller reach them? For example... I would like to have the following urls work correctly:
Admin/Index
Admin/Profile/Index
Admin/Profile/Edit/1
Admin/Group/Index
Admin/Group/Edit/1
So, would I create a folder for Profile and Group as a subfolder within Admin?
I tried this and to map a route in the Global file but that does not seem to be working.
Seems like you're trying to create admin panel and by putting other controller related actions into admin controller. I believe it's not the most efficient way. You could simply do like this:
Use RedirectToAction as return if needed for admin links
Admin/Index
Admin/Profile
Admin/Group
And put rest to appropriate controllers
Profile/Index
Profile/Edit/1
Group/Index
Group/Edit/1
Also add [Authorize(Roles = "Administrator")] and [AcceptVerbs(HttpVerbs.Post)] for create/edit/delete actions
Just make the return action be like this:
return View("Profile/Index");
That will make the trick for the controller find the "subview". For mapping the URLs to the right controller you can use the routing system, but ignore the subview, just map to the right controller and let the controller handle the correct view.
You could create your own ViewEngine and override where to look for the files something like this
public class MyViewEngine : WebFormViewEngine
{
public MyViewEngine()
{
ViewLocationFormats = new[] {
"~/{0}.aspx",
"~/{0}.ascx",
"~/Views/{1}/{0}.aspx",
"~/Views/{1}/{0}.ascx",
"~/Views/Shared/{0}.aspx",
"~/Views/Shared/{0}.ascx",
};
MasterLocationFormats = new[] {
"~/{0}.master",
"~/Shared/{0}.master",
"~/Views/{1}/{0}.master",
"~/Views/Shared/{0}.master",
};
PartialViewLocationFormats = ViewLocationFormats;
}
}
Then in your application start add
ViewEngines.Engines.Add(new MyViewEngine());
There's another option that is using the concept of Areas in order to achieve a global grouping of views and controllers as described in this interesting Billy McCafferty's post:
Creating MVC "Areas" as Subfolders under Views
The code is available so you can check out how everything is done, but basically replaces the ViewEngine with another, similar to the original but with different management of the view locations and registers routes according to the areas defined.

Resources