Контроллеры области вызываются из корневого запроса


У меня есть некоторая область в моем ASP.NET применение MVC3:

namespace MyProject.Areas.myarea
{
    public class myareaAreaRegistration : AreaRegistration
    {
        public override string AreaName
        {
            get
            {
                return "myarea";
            }
        }

        public override void RegisterArea(AreaRegistrationContext context)
        {
            context.MapRoute(
                "myarea_default",
                "myarea/{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional }
            );
        }
    }
}

Эта область содержит контроллер" Hello "с действием "Smile".

В глобальном масштабе.файл asax для всего проекта у меня есть:

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

    }

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    }

Поэтому, когда я запрашиваю "localhost / myarea / hello / smile", он вызывает соответствующий контроллер, как и ожидалось.

Но! Когда я запрашиваю "localhost / hello / smile", он все еще вызывает контроллер hello! При этом он ищет представления не в папке myarea/Views, а в папке ~ / Views для " root" (вне зоны) уровень проекта.

Как это исправить, чтобы сервер выдал исключение 404, что ресурс не найден, так же, как я запросил несуществующий контроллер?

UPD: контроллеры в области находятся в пространстве имен:

namespace MyProject.Areas.myarea.Controllers
{
    public class HelloController : Controller

...
}

Контроллеры на уровне "root" находятся в пространстве имен:

namespace MyProject.Controllers
{
    public class AnotherRootController : Controller
...
}

Поэтому я попробовал это в global.asax:

    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 }, 
            new [] { "MyProject.Controllers" } //Namespace
        );

    }

Я думал, что это ограничит этот маршрут только контроллерами "корневого" уровня, так как они находятся в MyProject.Контроллеры пространство имен. Это не сработало. Контроллеры области по-прежнему вызываются с запросом без имени области в нем.

Может быть, кто-то может объяснить, почему?

1 3

1 ответ:

Вы можете задать UseNamespaceFallback=false datatoken при регистрации маршрута по умолчанию в вашем глобальном каталоге.asax, ограничив его поиск только контроллеров в данном пространстве имен. Вы можете взглянуть на следующий пост в блоге .

Итак, чтобы привести это в действие, добавьте ограничение пространства имен к вашей регистрации области:

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

И в вашем Global.asax Установите маркер UseNamespaceFallback data в false при регистрации маршрута по умолчанию, чтобы ограничить его до заданного значения. пространство имен:

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 },
        new[] { "MyProject.Controllers" }
    ).DataTokens["UseNamespaceFallback"] = false;
}