MVC5中如何防止使用错误区域的控制器

Sam*_*Sam 0 c# asp.net-mvc asp.net-routing asp.net-mvc-5

我的 MVC 应用程序是在根/全局级别设置控制器的。这些没有明确的区域。我还有一个“管理”区域。以 /admin/ 开头的 URL 将路由到管理区域中的匹配控制器。其他 URL 将路由到匹配的全局控制器。这在大多数情况下工作正常。

我遇到的问题是,如果 URL 与管理区域中的控制器匹配,而全局区域中不存在同名控制器,则请求会错误地路由到管理区域中的控制器。我知道这种情况正在发生,因为我在相关控制器中的匹配操作上放置了断点。

例如,我有一个CalendarController在管理区域中调用的控制器。当我访问时/admin/calendar,它起作用,因为它在 中找到了操作和相应的视图Areas/Admin/Views/Calendar/Index.cshtml。当我访问时出现问题/calendar。我在根级别没有名为 Calendar 的控制器,但由于某种原因,它将请求路由到管理区域CalendarController,这是我不想要的。我希望它返回 404,因为CalendarController根级别不存在。相反,我收到错误,因为它正在根级别(位于 )搜索视图,/Views/Calendar/Index.cshtml即使匹配的控制器位于管理区域中。

如何防止在管理区域中搜索匹配的控制器,除非 URL 中包含 /admin ?

这是相关的路由代码,除了添加命名空间之外,基本上都是现有的。如果没有命名空间,问题仍然会发生。实际应用程序中有更多路线,但我在全新的 MVC 项目中得到了相同的行为。

public class AdminAreaRegistration : AreaRegistration 
{
    public override string AreaName 
    {
        get 
        {
            return "Admin";
        }
    }

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

public class RouteConfig
{
    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 }
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

错误页面

我所说的“根级别”控制器的含义Controllers/HomeController在此屏幕截图中。我想要不以 开头的 URL/admin只查看这些控制器。问题是它也在中搜索Areas/Admin/Controllers

解决方案浏览器

Bec*_*uzz 5

因此,MVC 路由引擎将在不同的命名空间中查找,以尝试找到匹配的控制器。您可以通过指定名称空间来解决此问题(就像您为管理区域所做的那样)。您还可以指定路由不使用 DataToken 搜索其他命名空间。

routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    namespaces: new [] { "AreaProblem.Controllers" }
    ).DataTokens["UseNamespaceFallback"] = false;
Run Code Online (Sandbox Code Playgroud)