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

时间:2014-03-16 12:04:06

标签: c# asp.net-mvc asp.net-mvc-5 asp.net-mvc-routing attributerouting

我有一个有多个区域的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" }
    );
}

控制器已正确加载,但无法找到视图(位于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

2 个答案:

答案 0 :(得分:4)

我看到两个选项:

  1. 明确并指定areaName [RouteArea("Default", AreaPrefix = "")],其中"默认"是您所在区域的名称,设置AreaPrefix = ""将获取应用程序根目录中的区域。
  2. 更改控制器所在的命名空间,以便最后一部分符合您所在地区的名称。
  3. 请注意,如果您所在地区的前缀是根(""),则需要明确您的行为[Route("...")]属性,以便他们不会贪婪地在您的申请中声明所有路线,并让您在其他一系列原因中摸不着头脑。

    <强>背景

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

    RouteAreaAttribute.AreaName文档很有用:

      

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

    通过将[RouteArea]应用于您的控制器,areaName默认为null,这会导致某些逻辑接管,并且会从目标控制器的命名空间中推断出区域名称。 #34;显然推断涉及抓住命名空间的最后部分,传统上该部分是&#34;控制器&#34;因为MVC开发人员已经被教导在Controllers文件夹中创建他们的控制器,并且默认情况下Visual Studio确定一个C#类&#39;基于文件夹结构的命名空间。

    为证明我的观点,您可以将DefaultController的命名空间从MyProject.Areas.Default.Controllers更改为MyProject.Areas.Default,切断&#34;。控制器&#34;。如果您重建并访问该操作,它将在&#34; Areas / Default&#34;下查找视图。我们都期待的文件夹:

    ~/Areas/Default/Views/Default/Index.aspx
    ~/Areas/Default/Views/Default/Index.ascx
    ...
    

    而不是&#34;区域/控制器&#34;没有人期待的文件夹:

    ~/Areas/Controllers/Views/Default/Index.aspx
    ~/Areas/Controllers/Views/Default/Index.ascx
    ...
    

    我明白为什么开发人员选择这样做,但不幸的是他们忽略了我们如何教授组织ASP.NET MVC代码以及Visual Studio如何为项目添加区域和控制器。它不完全是一个错误,而是一个比这更微妙和令人沮丧的东西。

答案 1 :(得分:0)

这里可能存在许多问题。当您声明一个区域时,第一个关闭的是一个单独的文件,其中包含到该区域的路径。您需要查找DefaultAreaRegistration.cs文件(应该在您的Regions / Default文件夹中)并检查那里的区域路径。它应该是这样的:

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

在这里注意2件事。在区域的路径中有一个明确的参考 - 默认/ {控制器} ...这就是MVC知道你在这个名为Default的案例区域中的特定区域的目标。要注意的第二件事是路由的名称是Default_default。原因是站点默认路由也称为DEFAULT。查看RouteConfig.cs文件,您将看到路由的名称是默认的。因此,如果您明确指出两条路线相同,它们将相互覆盖。

我怀疑这两件事中有一件是你问题的原因......