MVC 2 ОбластьРегистрация Маршруты Заказ

Я заметил, что в MVC 2 Preview 2 AreaRegistration загружает маршруты для каждой области в произвольном порядке. Есть ли хороший способ получить один раньше другого?

Например, у меня есть две области - "Сайт" и "Администратор". Оба имеют контроллер "Блог".

Я хотел бы следующее:

/admin/ --> go to Admin's Blog controller
/       --> go to Site's Blog controller. 

Проблема в том, что сначала загружается маршрут сайта, поэтому он совпадает {controller}/{action}/{id} вместо admin/{controller}/{action}/{id} когда я иду на URL "/ Admin/". Затем я получаю 404, потому что в области "Сайт" нет контроллера администратора.

Обе области по умолчанию для контроллера "Блог". Я понимаю, что мог бы просто site/{controller}/... как URL, но я бы предпочел, чтобы это было в корне, если это возможно. Я также попытался сохранить маршрут по умолчанию в глобальной функции RegisterRoutes, однако затем он не отправляется в область "Сайты".

Заранее спасибо!

4 ответа

Решение

В настоящее время невозможно заказать участки. Тем не менее, я думаю, что имеет смысл попытаться сделать каждую область как можно более независимой от других областей, чтобы порядок не имел значения.

Например, вместо того, чтобы иметь маршрут по умолчанию {controller}/{action}/{id}, возможно, замените его конкретными маршрутами для каждого контроллера. Или добавьте ограничение к этому маршруту по умолчанию.

Мы обдумываем варианты, чтобы разрешить заказ, но не хотим слишком усложнять функцию.

Помимо того, что сказал Haacked, очень много можно заказать регистрации области (и, следовательно, их маршруты). Все, что вам нужно сделать, это зарегистрировать каждую область вручную в любом порядке. Это не так гладко, как вызов RegisterAllAreas(), но это определенно выполнимо.

protected void Application_Start() {
    var area1reg = new Area1AreaRegistration();
    var area1context = new AreaRegistrationContext(area1reg.AreaName, RouteTable.Routes);
    area1reg.RegisterArea(area1context);

    var area2reg = new Area2AreaRegistration();
    var area2context = new AreaRegistrationContext(area2reg.AreaName, RouteTable.Routes);
    area2reg.RegisterArea(area2context);

    var area3reg = new Area3AreaRegistration();
    var area3context = new AreaRegistrationContext(area3reg.AreaName, RouteTable.Routes);
    area3reg.RegisterArea(area3context);
}

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

Для справки,

В MVC3 (не знаю о MVC2), когда вы просто хотите отобразить root на определенную область / контроллер, вы можете просто использовать глобальный маршрут. Просто не забудьте указать пространство имен / область.

    routes.MapRoute(
      "CatchRoot", "",
      new { controller = "SITEBLOG-CONTROLLER-NAME", action = "Index"} 
     ).DataTokens.Add("area", "SITE-AREA-NAME");

Я делаю это решение:

AreaUtils.cs

    using System;
    using System.Web.Mvc;
    using System.Web.Routing;

    namespace SledgeHammer.Mvc.Site
    {
        public static class Utils
        {
                public static void RegisterArea<T>(RouteCollection routes,
    object state) where T : AreaRegistration

            {
                 AreaRegistration registration =
     (AreaRegistration)Activator.CreateInstance(typeof(T));

                    AreaRegistrationContext context =
     new AreaRegistrationContext(registration.AreaName, routes, state);

                    string tNamespace = registration.GetType().Namespace;
                    if (tNamespace != null)
                {
                    context.Namespaces.Add(tNamespace + ".*");
                }

                registration.RegisterArea(context);
            }
        }

    }

В global.asax:

Utils.RegisterArea<SystemAreaRegistration>(RouteTable.Routes, null);
Utils.RegisterArea<ClientSitesAreaRegistration>(RouteTable.Routes, null);

//AreaRegistration.RegisterAllAreas(); do not dublicate register areas

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

Это мой район регистрации в качестве примера:

namespace SledgeHammer.MVC.Site.Areas.System
{
    public class SystemAreaRegistration : AreaRegistration
    {
        public override string AreaName
        {
            get { return "System"; }
        }

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



namespace SledgeHammer.MVC.Site.Areas.ClientSites
{
    public class ClientSitesAreaRegistration : AreaRegistration
    {
        public override string AreaName
        {
            get { return "ClientSites"; }
        }

        public override void RegisterArea(AreaRegistrationContext context)
        {
            context.MapRoute(
                "ClientSites_default",
                "{controller}/{action}/{id}",
                new { controller = "Site", action = "Index", id = UrlParameter.Optional },
                new { Host = new SiteInGroups("clients") }
            );
        }
    }
}
Другие вопросы по тегам