gpt4 book ai didi

asp.net-mvc-2 - 未指定区域时,ASP.NET MVC 2 RC 2返回特定于区域的 Controller

转载 作者:行者123 更新时间:2023-12-04 17:05:30 25 4
gpt4 key购买 nike

我有一个基本的MVC 2(RC2)站点,其中包含一个基本级别的 Controller (“主页”),以及一个区域(“Admin”)和一个 Controller (“摘要”)。当我调用http://website/Abstract时-即使我未在URL中指定Area,也将调用Admin区域中的Abstract Controller 。更糟糕的是-它似乎不知道它在Admin下,因为它找不到关联的 View 并仅返回:

The view 'Index' or its master was not found. The following locations were searched:
~/Views/Abstract/Index.aspx
~/Views/Abstract/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx

难道我做错了什么?这是一个错误吗?一项功能?

最佳答案

我和我的 friend 在ASP.NET MVC 2中都遇到了Areas的相同问题。到目前为止,我们发现了一个“hack”,似乎可以正常工作。对于tl; dr版本,请参见此答案的底部。

在“管理员”区域的“AdminAreaRegistration.cs”类中,您可能会获得类似于以下内容的信息:

// Web/Areas/Admin/AdminAreaRegistration.cs

public override void RegisterArea(AreaRegistrationContext context) {
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}

因此,当您请求“ http://website/Abstract”时,“Admin_default”路由与该请求不匹配是有意义的。因此,通过设计,MVC框架尝试将请求与任何其他定义的路由进行匹配。如果使用Visual Studio中的MVC工具创建Web项目,则将在“Global.asax”文件(位于Web项目的根目录)中定义一个“默认”路由。它看起来应该类似于:
// Web/Global.asax.cs

public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

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

“默认”路由成功匹配了对“ http://website/Abstract”的请求,其中“controller” =“Abstract”,“action” =“Index”(默认值)和“id” = UrlParameter.Optional(默认值)。到目前为止,这是正确的和预期的行为。

现在,MVC框架将尝试加载“抽象” Controller 。按照设计,MVC将搜索一个名为“AbstractController”的类,该类将“Controller”扩展到Web项目的文件/命名空间层次结构中的任何位置。重要的是要注意,Controller的文件位置和 namespace 不会影响MVC的查找能力。换句话说,仅仅是因为您已将“AbstractController”放置在名为“Areas\Admin\Controllers”的文件夹中,并将命名空间更改为“Web.Areas.Admin.Controllers”,而不是“Web.Controllers” ,并不表示MVC不会使用它。

当MVC在“AbstractController”中执行“Index”操作(很可能仅返回“View()”)时,MVC就会感到困惑,因为它不知道在哪里可以找到“Index” View 。由于MVC已匹配非区域路由(Global.asax中的“默认”路由),因此它认为匹配的 View 应位于非区域 View 文件夹中。因此,您会收到熟悉的错误消息:
The view 'Index' or its master was not found. The following locations were searched:
~/Views/Abstract/Index.aspx
~/Views/Abstract/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx

与您一样,我们不希望将“ http://website/Abstract”的请求解析为“Admin”区域的“AbstractController”;只有“ http://website/Admin/Abstract”应该起作用。我想不出为什么有人会想要这种行为。

一个简单的解决方案是删除Global.asax中的“默认”路由,但这会破坏所有常规的非区域 Controller / View 。对于大多数人来说,这可能不是一个选择。

因此,我们认为可以限制MVC用于Global.asax中“默认”路由匹配的请求的 Controller 的集合:
// Web/Global.asax.cs

public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

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

不。即使“AbstractController”的命名空间是“Web.Areas.Admin.Controllers”,并且(显然)不是“Web.Controllers”,对“ http://website/Abstract”的请求仍将在“Admin”区域中使用“AbstractController”。这是非常令人困惑的。看来此白名单对MVC的Controller分辨率没有明显的影响。

-tl; dr答案从此处开始-

经过一番黑客攻击后,我们找到了如何强制MVC仅在白名单 namespace 中使用Controllers的方法。
// Web/Global.asax.cs

public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new {controller = "Home", action = "Index", id = UrlParameter.Optional},
new[] {"Web.Controllers"}
).DataTokens["UseNamespaceFallback"] = false; // Added this line
}

将“默认”路由上的DataTokens词典的“UseNamespaceFallback”键设置为false。现在,当我们请求“ http://website/Abstract”时,“Default”路由仍然会被匹配(这是有效的行为!),但是MVC不会使用不在定义 namespace 内的任何Controller;在这种情况下,只有“Web.Controllers”命名空间中的Controller有效。最后,这就是我们想要的功能!我们无法弄清楚为什么这不是默认行为。奇怪吧?

希望这可以帮助。

关于asp.net-mvc-2 - 未指定区域时,ASP.NET MVC 2 RC 2返回特定于区域的 Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2314524/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com