2009-10-28 7 views
12

Mir ist aufgefallen, dass AreaRegistration in MVC 2 Preview 2 die Routen für jeden Bereich in einer beliebigen Reihenfolge lädt. Gibt es eine gute Möglichkeit, eines vor dem anderen zu bekommen?MVC 2 AreaRegistration Routes Auftrag

Zum Beispiel habe ich zwei Bereiche - "Site" und "Admin". Beide haben einen "Blog" -Controller.

Ich möchte folgendes:

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

Das Problem ist, dass es die Website der Route wird geladen erste, so ist es {controller}/{action}/{id} statt admin/{controller}/{action}/{id} passend, wenn ich auf die URL „/ admin /“ gehen. Ich bekomme dann einen 404, weil es im Bereich "Site" keinen Admin-Controller gibt.

Beide Bereiche standardmäßig auf den "Blog" -Controller. Ich weiß, ich könnte einfach site/{controller}/... als die URL setzen, aber ich würde es lieber an der Wurzel haben, wenn möglich. Ich versuchte auch, die Standardroute in der globalen RegisterRoutes-Funktion zu behalten, sie wird dann jedoch nicht an den Bereich "Sites" gesendet.

Vielen Dank im Voraus!

Antwort

7

Derzeit ist es nicht möglich, Bereiche zu bestellen. Ich denke jedoch, dass es sinnvoll ist, jeden Bereich so unabhängig von anderen Bereichen wie möglich zu gestalten, damit die Reihenfolge keine Rolle spielt.

Zum Beispiel kann anstelle der Standardroutine {controller}/{aktion}/{id} diese durch bestimmte Routen für jeden Controller ersetzt werden. Oder fügen Sie der Standardroute eine Einschränkung hinzu.

Wir beschäftigen uns mit Optionen, um die Bestellung zu ermöglichen, aber wir möchten die Funktion nicht übermäßig komplizieren.

+0

Hey Phil, danke für die Erklärung. Ich landete meine "Website" aus Bereichen und es ist jetzt der Bereich "Standard/Nicht-Bereich" (mit Ansichten und Controllern im Stammverzeichnis). Ich habe dann meinen Namespace-Parameter auf die Standard-Controller gesetzt, um den "mehrdeutigen Controller" -Fehler zu vermeiden. Außerdem könnte ich wahrscheinlich Einschränkungen wie etwa^((?! admin). *) Gesetzt haben, um den Admin in den Site-Bereich Routen zu ignorieren. Ich stimme zu, Hinzufügen von mehr Komplexität ist nicht groß, obwohl es scheint, dass MVC 1 (nicht Gebiet) Routen potenziell stark auf Ordnung verlassen können. Danke! – Jason

+0

Der Routing-Prozess hängt normalerweise von der Reihenfolge der Regeln ab, daher kann die Funktion "Bestellung" wichtig sein. – twk

+0

Bitte beachten Sie meine Antwort für zwei Techniken, mit denen Sie die Bereichsregistrierung (und damit ihre Routen) in beliebiger Reihenfolge bestellen können. – Eilon

30

Abgesehen von dem, was Haacked gesagt hat, ist es sehr gut möglich, Gebietsanmeldungen (und damit ihre Routen) zu bestellen. Alles, was Sie tun müssen, ist jeden Bereich manuell in der von Ihnen gewünschten Reihenfolge zu registrieren. Es ist nicht so elegant wie RegisterAllAreas(), aber es ist definitiv machbar.

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

Eine andere Möglichkeit ist, den Code für RegisterAllAreas zu nehmen(), kopieren Sie sie in Ihre eigene App, und Ihre eigenen Mechanismus bauen die Reihenfolge zu bestimmen. Es ist ziemlich viel Code zu kopieren, wenn Sie alle die Phantasie Caching-Logik möchten, die die integrierte Methode, aber Ihre App möglicherweise nicht einmal benötigt.

+0

Große Antwort. Außerdem weniger Code, wenn Sie eine Methode erstellen, und dann ist es eine Zeile Code pro Bereich. – CRice

4

Ich mache diese Lösung:

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

    } 

In global.asax:

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

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

Keine requred Änderungen erzeugt Bereich Registrierungscode. Ich benutze auch benutzerdefinierte Regel in Routen, um Routen nach Typ der Domäne in Anfrage (System-Domain oder Benutzer-Site) zu filtern.

Das ist mein Bereich Registrierungen als Beispiel:

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

Ihre util-Klasse ist genial, weil sie darauf hinweist, dass Sie den Namespace für die Bereiche hinzufügen müssen, sonst wird der Router nicht mit den Controllern verbunden. –

4

Als Referenz

In MVC3 (weiß nicht, über MVC2), wenn Sie root auf einen bestimmten Bereich/Controller zuordnen möchten nur Sie könnte einfach eine globale Route verwenden. Denken Sie daran, den Namespace/Bereich anzugeben.

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

+1 - Dies ist eine schöne Lösung, da alles in Bereiche mit Ausnahme von einem gruppiert werden kann Bereich als Catch-All mit einer saubereren URL dienen. –

+0

Funktioniert perfekt! Erlaubt mir, alle Controller in Bereichen zu haben, anstatt "spezielle" und tatsächliche Bereiche. Für alle, die das gleiche möchten, registrieren Sie die Standardroute in der Routenkonfiguration. – FDIM