ASP.NET MVC Areas: How to hide “Area” name in URL?

我的未来我决定 提交于 2019-11-30 03:30:46
Artiom Chilaru

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 :)

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!