ASP.NET MVC 区域:如何隐藏“区域”网址中的名称?

发布于 2024-08-29 15:47:15 字数 835 浏览 8 评论 0原文

运行 MVC 2 Areas 示例时有一个博客区域和博客控制器,URL 如下所示:

http://localhost:50526/Blog/Blog/ ShowRecent 格式为:

RootUrl / AreaName / ControllerName / ActionName

刚刚发现了 MVC Areas,这似乎是组织代码的好方法,即为每个部分创建一个区域,在我的例子中,每个部分都有自己的控制器。这意味着每个 AreaName = ControllerName。这样做的效果是 Url 中的双 AreaName/ControllerName 路径,例如上面的 /Blog/Blog/

没有对路由的完全清晰的了解,我如何设置路由以不显示 AreaName?

编辑:

我正在尝试减少路由的工作量,因为这些路由似乎会相互影响(即需要特定的排序),并且可能会引起严重的头痛:-)在将现有的 Webform 应用程序转换为 MVC 时,我已经转换了几个核心部分,每个部分都有一个控制器和相当数量的视图/操作,尽管大多数数据访问代码都在程序集中,但模型/视图数据类的数量正在增长......我目前正在创建这些部分(或区域)的根模型/视图文件夹中的子文件夹,并希望创建区域能够以相同的方式工作,除了组织代码(使用覆盖该区域的基本路线) 对此有何评论?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

春庭雪 2024-09-05 15:47:15

在每个区域的文件夹中,您将看到一个 *AreaName*AreaRegistration.cs 文件。这是存储区域路由规则的位置。默认情况下,在生成它们时,它们将在其他所有内容之前包含区域名称。问题是:如果从路线中删除区域名称“文件夹”,路线将捕获所有“标准”{controller}/{操作}/{id} 请求。这显然不是您想要的。

要克服这个问题,您可以根据该路由中存在的控制器名称在路由上添加正则表达式过滤器。缺点是什么?您将无法在应用程序中拥有两个具有相同名称的控制器(至少不使用标准路线..您总是可以想到不同的路线来访问它们:))

最后..具有以下结构:

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

你应该拥有的是这样的:
在 BlogAreaRegistration.cs 中:

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

在 UserAreaRegistration.cs 中:

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

在 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);
}

请注意,在 global.asax 中,区域注册是第一位的! :)

更新:
根据您的问题更新:
如果您要使用区域,您必须考虑一件重要的事情:如果您有区域间链接,则还必须在链接中提供区域名称。例如,

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

你明白了。

关于多个模型/视图,目前我正在遵循这样的结构

/Code/ // 未移至库的帮助器、扩展类
/Models/Data/ // EF 类 + 验证类在这里
/Models/ViewModels/{controller}/ // 每个控制器存储的视图模型

到目前为止,它运行良好,并且我设法使解决方案保持相对有序。正如我所说,到目前为止我创建的唯一区域是Admin 区域,因为它与网站的其他部分有很大不同:)

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

删除→记忆 2024-09-05 15:47:15

只是为了回答您原来的问题,以防其他人正在阅读此内容:

不要命名您的[默认]控制器博客。这就是为什么你会得到博客/博客{area/controller}。您可以给它一个完全不同的名称:即博客/视图、博客/帖子、博客/最近等,或者使用默认名称,如主页。在这种情况下,如果您的区域外控制器中也有 home,则需要为默认控制器命名:

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

这将确保“/”和“/blog”转到适当的“home”控制器。如果您搜索重复的家庭控制器错误,您会发现更多相关信息。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文