Default area view cannot be found when using MVC 5 RouteArea attribute

梦想与她 提交于 2019-12-10 19:40:59

问题


I have an MVC5 project with multiple areas. I have a default area (named Default) and within it, a default controller (named DefaultController). This is accessible at site route.

[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" }
    );
}

The controller is correctly loaded, but the view (located at Areas/Default/Views/Default/Index.cshtml) cannot be found. Why is MVC not looking in the right place?

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

回答1:


I see two options:

  1. Get explicit and specify the areaName with [RouteArea("Default", AreaPrefix = "")] where "Default" is the name of your area and setting AreaPrefix = "" gets the area in the root of your application.
  2. Change the namespace your controller is in so that the last part matches your area's name.

Note that if your area's prefix is the root ("") you need to be very explicit with your action [Route("...")] attributes so that they don't greedily claim all of the routes in your application, and leave you scratching your head for a whole other slew of reasons.

Background

When the RouteAreaAttribute is applied without supplying the areaName or the areaName supplied is null you may get this odd error, or your action may use an incorrect view (if for example you have created ~/Views/Shared/Index.cshtml for some other purpose).

The RouteAreaAttribute.AreaName docs are helpful:

(The AreaName property) gets the area name to set for all the routes defined in the controller. If the value is null, an attempt will be made to infer the area name from the target controller's namespace.

By applying [RouteArea] to your controller the areaName defaults to null which causes some logic to take over that will "infer the area name from the target controller's namespace." Apparently inferring involves grabbing the last part of the namespace, traditionally that part is "Controllers" because MVC developers have been taught to create their controllers in the Controllers folder, and by default Visual Studio determines a C# class' namespace based on folder structure.

To prove my point you can change the DefaultController's namespace from MyProject.Areas.Default.Controllers to MyProject.Areas.Default, chopping off ".Controllers". If you rebuild and visit that action it will look for views under the "Areas/Default" folder like we all expect:

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

Instead of under the "Areas/Controllers" folder like no one expects:

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

I get why the developers chose to do it this way, but it's unfortunate they ignored how we've been taught to organize ASP.NET MVC code and how Visual Studio adds areas and controllers to projects. It's not exactly a bug, instead it's something more subtle and frustrating than that.




回答2:


There could be a number of issues here. 1st off when you declare an area there is a separate file that contains the route to that area. You need to look for DefaultAreaRegistration.cs file (should be in your Areas/Default folder) and check the area route in there. It should be something like this:

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

Notice 2 things here. There is a clear reference in the path to the Area - Default/{controller}... This is how MVC knows you are targeting a specific area in this case area named Default. 2nd thing to notice is the name of the route is Default_default. The reason for this is that site Default route is also named DEFAULT. Look in your RouteConfig.cs file and you will see the name of the route is default. So if you name two routes the same obviously they will overwrite each other.

I suspect one of these two things is the cause of your problem...



来源:https://stackoverflow.com/questions/22436573/default-area-view-cannot-be-found-when-using-mvc-5-routearea-attribute

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!