Как зарегистрировать зону с помощью app_start или webactivator?

Я бы не хотел звонить

AreaRegistration.RegisterAllAreas ()

в моем global.asax, потому что я пытаюсь переместить всю логику запуска в отдельные классы внутри папки App_Start. Однако мне не удалось заставить это работать. Первый вариант попытался использовать такой код:

[assembly: PreApplicationStartMethod(typeof(Startup), "PreInit")]
namespace Foo
{
  public class Startup {}
}

Где PreApplicationStartMethod исходит из пространства имен System.Web. В этом случае вызов на регистрацию участков происходит слишком рано.

Второй подход, основанный на этой публикации Дэвида Эббо, использует WebActivator: using System.Web.Mvc;

    [assembly: WebActivatorEx.PostApplicationStartMethod
(typeof(AreaDemo.AreaConfig), "RegisterAreas")]
    namespace AreaDemo
    {
        public class AreaConfig
        {
            public static void RegisterAreas()
            {
                AreaRegistration.RegisterAllAreas();
            }
        }
    }

К сожалению, хотя ошибка не возникает, попытка перейти в область не удалась (как будто регистрация никогда не происходила).

Как правильно регистрировать области в ASP.NET MVC 5 из класса запуска с использованием директивы сборки, а не прямого вызова из Global.asax?

Обновление 1: вот мой регистрационный код области:

public class AdminAreaRegistration : AreaRegistration
{
    public override string AreaName
    {
        get
        {
            return "Admin";
        }
    }

    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute(
            "Admin_default",
            "Admin/{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            new string[] { "AreaDemo.Areas.Admin.Controllers" }
            );
    }
}

По какой-то причине значения по умолчанию игнорируются, но переход в / admin / home / index / 0 работает. / admin, / admin / home и / admin / home / index все 404.


person ssmith    schedule 15.10.2014    source источник
comment
Я думал, что этого можно достичь, сделав Foo HttpModule, например Foo: IHttpModule. Затем вы можете поместить AreaRegistration.RegisterAllAreas () в реализованный метод Init HttpModule. Для вызова Init вы должны вызвать это в своем Startup: DynamicModuleUtility.RegisterModule (GetType ()). Это почти работает, так как сейчас подходящее время и не слишком рано, но проблема в том, что Init вызывается несколько раз, поэтому регистрация маршрута для области дублируется, что приводит к YSOD :(   -  person Basem    schedule 15.10.2014
comment
Интересно, что при использовании второго подхода маршруты по умолчанию не работают, а конкретные маршруты работают. То есть переход к / Admin не выполняется, но этот маршрут работает нормально: localhost: 36237 / admin / home / index / 0   -  person ssmith    schedule 15.10.2014


Ответы (1)


Я считаю, что это проблема с заказом (что, похоже, вы тоже подозреваете). Я думаю, что области регистрируются после события Application_Start, и, таким образом, маршруты областей регистрируются после маршрутов вне области.

Причина того, что 4-сегментный URL (/admin/home/index/123) работает, заключается в том, что он не может соответствовать маршруту «по умолчанию» приложения MVC. Таким образом, этот маршрут по умолчанию пропускается (потому что он соответствует только 1-, 2- и 3-сегментным URL-адресам), а маршрутизация найдет зависящий от области маршрут, который может обрабатывать 4-сегментный URL-адрес. 1-, 2- или 3-сегментный URL-адрес будет соответствовать маршруту вне области, но, конечно, нет контроллеров вне областей для обработки такого URL-адреса, и поэтому возвращается 404.

Если я правильно понял, вы хотите, чтобы области регистрировались после Application_Start, но до того, как произойдет что-либо "еще"? К сожалению, мне не известно ни о каком конкретном событии, чтобы справиться с этим. Из IHttpModule вы могли бы, возможно, попробовать обработать событие, такое как BeginRequest, которое происходит очень рано, быстро выполнить регистрацию там только один раз (то есть не регистрировать материал в каждом запросе!), И это должен позволить вам проскользнуть до того, как маршрутизация ASP.NET выполнит свою работу (что происходит немного позже, во время PostResolveRequestCache).

Полная альтернатива этому - использовать атрибут routes, который нравится многим, потому что он помогает избежать проблем с упорядочением.

person Eilon    schedule 25.10.2014