ASP.NET MVC Areas: How to hide "Area" name in URL?
Asked Answered
Q

2

15

When running the MVC 2 Areas example that has a Blog Area and Blog Controller the URL looks like this:

http://localhost:50526/Blog/Blog/ShowRecent in the format:

RootUrl / AreaName / ControllerName / ActionName

Having just discovered MVC Areas, it seem like a great way to organise code, ie create an Area for each section, which in my case each section has its own controller. This means that each AreaName = ControllerName. The effect of this is the double AreaName/ControllerName path in the Url eg /Blog/Blog/ above

Not having a complete clear understanding of routing, how could I setup routing to not show the AreaName?

EDIT:

I am trying to reduce the amount of work with routes as these appear to effect each other (ie require specific ordering) and may cause major headaches :-) In converting an existing webform app to MVC, I have converted a couple of core sections, These have one Controller each and a fair amount of View/Actions and although most of the Data Access is code is in assemblies the number of Model/ViewData classes is growing... I am currently creating sub-folders in the Root Models/Views folders for these sections (or Areas) and was hoping that creating Areas would work the same way except having the code organised (with the use of a basic route that covers the Area) Any comment on this?

Quick answered 21/4, 2010 at 10:43 Comment(3)
Out of curiosity, if you don't want the extra folder, why implement your application that way?Aesthetically
Btw.. Don't overdo it with the routes.. If you make an area that will have one single controller, then are you sure it needs a separate area in the first place? :)Incumbency
@GalacticCowboy, Artiom: Good points and have added more comments above...It may look like Areas may not be the way to go, or indeed something to start using when we need to start organising larger/specific sections.Quick
I
20

Inside each area's folder you'll see a *AreaName*AreaRegistration.cs file. This is where the area routeing rules are stored. By default, as they are generated, they will contain the area name ahead of everything else.. The problem is: if you remove the area name "folder" from the route, the route will catch all "standard" {controller}/{action}/{id} requests. Which is obviously not what you want..

To overcome this you can add the regex filters on the routes, based on the controller names present in that route. The drawback? You won't be able to have two controllers with the same name within the app (at least not using the standard route.. You can always think of a different route to access them :) )

In the end.. Having this structure:

/Areas
/Areas/Blog/Controllers/BlogController.cs
/Areas/Blog/Controllers/FeedController.cs
/Areas/User/Controllers/UserController.cs
/Controllers/PageController.cs

What you should have is sth like this: In BlogAreaRegistration.cs:

context.MapRoute(
    "Blog_default",
    "{controller}/{action}/{id}",
    new { action = "Index", id = UrlParameter.Optional },
    new { controller = "(Blog|Feed)" }
);

In UserAreaRegistration.cs:

context.MapRoute(
    "User_default",
    "{controller}/{action}/{id}",
    new { action = "Index", id = UrlParameter.Optional },
    new { controller = "(User)" }
);

In Global.asax.cs:

public static void RegisterRoutes(RouteCollection routes)
{
    context.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}
protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterRoutes(RouteTable.Routes);
}

Note that in global.asax area registrations come first! :)

UPD: Based on your question update: There us one major thing that you'll have to take into consideration if you will use areas: If you have a inter-area link, you'll also have to provide the area name in the link. E.g.

<%: Html.ActionLink("Link text", "Action", "Controller", new { area = "Blog", id = 4, title = "page-title" }); %>

You get the idea.

Regarding the multiple models/views, at the moment I'm following a structure like this

/Code/ // helper, extension classes that aren't moved to libraries
/Models/Data/ // The EF classes + validation classes are here
/Models/ViewModels/{controller}/ // view models stored per controller

So far it works fine, and I managed to keep the solution relatively organised. As I stated, the only area that I created so far is the Admin area because it's that much different from the rest of the website :)

Incumbency answered 21/4, 2010 at 11:1 Comment(8)
Thanks for that! I will need to have a play with this (and a good think) to see what benefit is gained by using Areas in the current situation...Quick
Just to give you my current situation: I'm working on my own blog engine (probably not public, written just for myself). At the moment most of the Controllers are in the default /Controllers folder. Pages, registration/authentication, comments, file downloads etc. But I have created an Admin area because I think it should be separated from the regular code + has a different look (separate Contect folder etc). In the end it's up to you )Incumbency
Added an update to the answer, answering to your update to the question.. Umm.. that sounded weird :DIncumbency
Taking everything I have learned so far regarding Areas, its probably worth not having them in this instance, or until there is a larger sections that is isolated from the rest (eg Admin as you say)Quick
Sounds good.. And btw, other than Admin, I haven't thought of any other area that I would create so far.. ) Question answered? :PIncumbency
I have tried out the routing as you've suggested and that did solve the problem I had. I have done this on a part of the application that doesnt interact with any other in fact its almost like a stand-alone app. This leads me to think that using Areas could be a good way of building a core MVC framework for multiple applications where these different applications are dropped in as new Areas? I will keep that part of the application in an Area for now and decide when I know more...Thanks for your help.Quick
I guess that's the idea behind areas... The good part about keeping them together in a single web app is that they share configuration and session state, and there can be other in-process interaction between each area, while they're still strictly separated from each other...Incumbency
@Artiom - in my MVC2 app, the Admin section is also the only "Area" I have. It's got a couple of controllers, etc., so it makes sense to do vs. an area with one controller. I could see other uses for areas down the road.Aesthetically
I
1

Just to answer your original question, in case someone else is reading this:

Do not name your [default] controller blog. This is why you get blog/blog {area/controller}. You can either give it a completely different name: i.e., blog/view, blog/posts, blog/recent, etc. or, a default like home. in this case, if you also have home in your out-of-area controllers, you'll want to namespace your default controller:

routes.MapRoute("Default",
  "{controller}/{action}/{id}",
  new { controller = "Home", action = "Index", id = UrlParameter.Optional},
  new[] { *appname*.Controllers" });

This will ensure that "/" and "/blog" go to the appropriate "home" controller. If you search for the duplicate home controller error you'll find more on this.

Infidelity answered 11/5, 2010 at 18:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.