Вопрос

Я заметил, что в 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, однако затем он не отправляется в область "Сайты".

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

Это было полезно?

Решение

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

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

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

Другие советы

Помимо того, что сказал Хаакед, очень возможно заказать регистрацию областей (и, следовательно, их маршруты). Все, что вам нужно сделать, это зарегистрировать каждую область вручную в любом порядке. Это не так гладко, как вызов 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 (), скопировать его в собственное приложение и создать собственный механизм определения порядка. Копировать довольно много кода, если вы хотите использовать всю логику кеширования, которую использует встроенный метод, но вашему приложению это может даже не понадобиться.

Я принимаю это решение:

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

Для справки,

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

    routes.MapRoute(
      "CatchRoot", "",
      new { controller = "SITEBLOG-CONTROLLER-NAME", action = "Index"} 
     ).DataTokens.Add("area", "SITE-AREA-NAME");
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top