2009-10-28 10 views
12

Noté que en MVC 2 Preview 2, AreaRegistration está cargando las rutas para cada área en un orden arbitrario. ¿Hay una buena manera de obtener uno antes que el otro?MVC 2 Rutas de registro de área Orden

Por ejemplo, tengo dos áreas: "Sitio" y "Administrador". Ambos tienen un controlador "Blog".

Me gustaría que el siguiente:

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

El problema es que se está cargando la ruta del sitio en primer lugar, por lo que está haciendo juego {controller}/{action}/{id} en lugar de admin/{controller}/{action}/{id} cuando voy a la URL "/ admin /". Luego obtengo un 404, porque no hay un controlador de administración en el área "Sitio".

Ambas áreas tienen por defecto el controlador "Blog". Me doy cuenta de que simplemente podría poner site/{controller}/... como la url, pero preferiría tenerlo en la raíz si es posible. También traté de mantener la ruta predeterminada en la función global RegisterRoutes, sin embargo, luego no se envía al área "Sitios".

¡Gracias de antemano!

Respuesta

7

Actualmente no es posible pedir áreas. Sin embargo, creo que tiene sentido tratar de hacer que cada área sea tan independiente de otras áreas como sea posible para que el orden no importe.

Por ejemplo, en lugar de tener la ruta predeterminada {controlador}/{acción}/{id}, tal vez reemplace eso con rutas específicas para cada controlador. O agregue una restricción a esa ruta predeterminada.

Estamos reflexionando sobre las opciones para permitir el pedido, pero no queremos complicar demasiado la función.

+0

Hola Phil, gracias por la explicación. Terminé moviendo mi "sitio" fuera de Áreas y ahora es la sección "predeterminada/no área" (con Vistas y Controladores en la raíz). Luego configuro mi parámetro de espacio de nombres para los controladores predeterminados para evitar el error de "controlador ambiguo". Además, podría haber establecido restricciones a algo como^((?! admin). *) Para ignorar el administrador en las rutas del área del sitio. Acepto, agregar más complejidad no es genial, aunque parece que las rutas mvc 1 (no de área) podrían depender mucho del pedido. Gracias! – Jason

+0

El proceso de enrutamiento generalmente depende del orden de las reglas, por lo que la función 'ordenar' puede ser importante. – twk

+0

Consulte mi respuesta para dos técnicas que le permiten ordenar el registro de área (y por lo tanto sus rutas) en cualquier orden. – Eilon

30

Aparte de lo dicho por Haacked, es muy posible solicitar registros de área (y por lo tanto sus rutas). Todo lo que tiene que hacer es registrar cada área manualmente, en el orden que desee. No es tan elegante como llamar a RegisterAllAreas(), pero definitivamente es factible.

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

Otra opción es tomar el código para RegisterAllAreas(), copiarlo en su propia aplicación, y construir su propio mecanismo para determinar el orden. Es un poco de código copiar si quieres toda la lógica de almacenamiento en caché que hace el método integrado, pero es posible que tu aplicación ni siquiera lo necesite.

+0

Gran respuesta. Además, menos código si hace un método y luego es una línea de código por área. – CRice

4

hago esta solución:

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

    } 

En global.asax:

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

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

No hay cambios a requred código de registro de área generada. También uso restricciones personalizadas en rutas para filtrar rutas por tipo de dominio en la solicitud (dominio del sistema o sitio del usuario).

Esta es mi área registros como ejemplo:

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

su clase util es impresionante porque indica que debe agregar el espacio de nombres para las áreas; de lo contrario, las rutas no se vincularán a los controladores –

4

Como referencia,

En MVC3 (no sé acerca MVC2) cuando lo que desea asignar a raíz de un área específica/controlador que podría simplemente usar una ruta global. Solo recuerda especificar el espacio de nombre/área.

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

+1 - Esta es una buena solución porque permite que todo se agrupe en áreas pero una área para servir como el todo incluido con una URL más limpia. –

+0

¡Funciona a la perfección! Me permite tener todos los controladores en áreas en lugar de 'especiales' y áreas reales. Para cualquiera que quiera lo mismo, registre la ruta predeterminada en la configuración de la ruta. – FDIM

Cuestiones relacionadas