使用MVC 5 RouteArea属性时找不到默认区域视图

Jon*_*han 3 c# asp.net-mvc asp.net-mvc-routing attributerouting asp.net-mvc-5

我有一个涉及多个领域的MVC5项目。我有一个默认区域(名为Default),其中有一个默认控制器(名为DefaultController)。这可以在站点路线上访问。

[RouteArea]
public class DefaultController : Controller
{
    [Route]
    public ActionResult Index()
    {
        return View("Index");
    }
}

public static void RegisterRoutes(RouteCollection routes)
{
    routes.LowercaseUrls = true;

    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapMvcAttributeRoutes();

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Default", action = "Index", id = UrlParameter.Optional },
        namespaces: new[] { "MyProject.Areas.Default.Controllers" }
    );
}
Run Code Online (Sandbox Code Playgroud)

控制器已正确加载,但是Areas/Default/Views/Default/Index.cshtml找不到视图(位于)。为什么MVC找不到正确的位置?

The view 'Index' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Areas/Controllers/Views/Default/Index.aspx
~/Areas/Controllers/Views/Default/Index.ascx
~/Areas/Controllers/Views/Shared/Index.aspx
~/Areas/Controllers/Views/Shared/Index.ascx
~/Views/Default/Index.aspx
~/Views/Default/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
~/Areas/Controllers/Views/Default/Index.cshtml
~/Areas/Controllers/Views/Default/Index.vbhtml
~/Areas/Controllers/Views/Shared/Index.cshtml
~/Areas/Controllers/Views/Shared/Index.vbhtml
~/Views/Default/Index.cshtml
~/Views/Default/Index.vbhtml
~/Views/Shared/Index.cshtml
~/Views/Shared/Index.vbhtml
Run Code Online (Sandbox Code Playgroud)

Jer*_*ook 5

我看到两个选择:

  1. 明确显示并使用来指定areaName[RouteArea("Default", AreaPrefix = "")]其中“默认”是您所在区域的名称,而AreaPrefix = ""settings将该区域获取到应用程序的根目录中。
  2. 更改控制器所在的名称空间,以使最后一部分与您所在区域的名称匹配。

请注意,如果您区域的前缀是根(“”),则需要非常明确地使用action [Route("...")]属性,以便它们不会贪婪地声明应用程序中的所有路由,并让您费尽心思原因。

背景

如果在RouteAreaAttribute未提供的情况下应用,areaName或者areaName提供的为null,则可能会收到此奇怪的错误,或者您的操作可能使用了错误的视图(例如,如果您~/Views/Shared/Index.cshtml出于其他目的而创建)。

RouteAreaAttribute.AreaName文档是有帮助的:

(AreaName属性)获取要为控制器中定义的所有路由设置的区域名称。如果该值为null,则将尝试从目标控制器的名称空间中推断区域名称。

通过将默认值应用于[RouteArea]控制器,areaName将导致某些逻辑接管,从而“从目标控制器的名称空间中推断区域名称”。显然,推断涉及获取名称空间的最后一部分,传统上该部分是“ Controllers”,因为已教会MVC开发人员在Controllers文件夹中创建其控制器,并且默认情况下,Visual Studio根据文件夹结构确定C#类的名称空间。

为了证明我的观点,您可以将DefaultController的命名空间从更改MyProject.Areas.Default.ControllersMyProject.Areas.Default,剪下“ .Controllers”。如果您重建并访问该操作,它将在“区域/默认”文件夹下寻找视图,就像我们都期望的那样:

~/Areas/Default/Views/Default/Index.aspx
~/Areas/Default/Views/Default/Index.ascx
...
Run Code Online (Sandbox Code Playgroud)

而不是没有人期望的在“区域/控制器”文件夹下:

~/Areas/Controllers/Views/Default/Index.aspx
~/Areas/Controllers/Views/Default/Index.ascx
...
Run Code Online (Sandbox Code Playgroud)

我知道为什么开发人员选择以这种方式进行操作,但是不幸的是他们忽略了我们被教导如何组织ASP.NET MVC代码以及Visual Studio如何为项目添加区域和控制器的方法。这不完全是一个错误,而是比它更微妙和令人沮丧的东西。