我有一个有多个区域的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
答案 0 :(得分:4)
我看到两个选项:
areaName
[RouteArea("Default", AreaPrefix = "")]
,其中"默认"是您所在区域的名称,设置AreaPrefix = ""
将获取应用程序根目录中的区域。请注意,如果您所在地区的前缀是根(""),则需要明确您的行为[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文件,您将看到路由的名称是默认的。因此,如果您明确指出两条路线相同,它们将相互覆盖。
我怀疑这两件事中有一件是你问题的原因......