2009-10-28 3 views
12

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

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

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

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

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

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

Заранее благодарен!

ответ

7

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

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

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

+0

Хей Фил, спасибо за объяснение. Я закончил перемещение своего «сайта» из областей, и теперь это раздел «default/non-area» (с представлениями и контроллерами в корне). Затем я задал свой параметр namespace paramater контроллерам по умолчанию, чтобы избежать ошибки «неоднозначного контроллера». Кроме того, я мог бы, вероятно, установить ограничения на что-то вроде^((! Admin). *), Чтобы игнорировать админа в маршрутах области сайта. Согласен, добавив, что сложность невелика, хотя кажется, что маршруты mvc 1 (non area) потенциально могут сильно зависеть от порядка. Спасибо! – Jason

+0

Процесс маршрутизации обычно зависит от порядка правил, поэтому функция «упорядочения» может быть важной. – twk

+0

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

30

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

+0

Отличный ответ. Кроме того, меньше кода, если вы создаете метод, а затем это одна строка кода для каждой области. – CRice

4

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

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 

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

Это моя регистрация область, как, например:

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

ваш класс util является удивительным, потому что он указывает, что вам нужно добавить пространство имен для областей, иначе маршруты не будут связаны с контроллерами. –

4

Для справки,

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

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

+1 - Это приятное решение, потому что оно позволяет группировать все в области, но одно область, которая будет использоваться для всех с более чистым URL-адресом. –

+0

Работает отлично! Позволяет мне иметь все контроллеры в областях, а не «специальные» и фактические области. Для тех, кто хочет этого, зарегистрируйте маршрут по умолчанию в конфигурации маршрута. – FDIM

Смежные вопросы