2009-07-10 21 views
13

Ich brauche pro unten eine MVC-Site mit URLs zu implementieren:ASP.net MVC benutzerdefinierte Route Handler/Einschränkungs

  • category1/product/1/wiki
  • category1/product/2/wiki
  • category1/sub-category2/product/3/wiki
  • category1/sub-category2/sub-Kategorie3/product/4/wiki
  • etc. etc.

wo die übereinstimmenden Kriterien ist, dass die URL mit "Wiki" endet.

Leider ist die unter allumfassende erst im letzten Teil der URL funktioniert:

routes.MapRoute("page1", // Route name 
       "{*path}/wiki", // URL with parameters 
       new { controller = "Wiki", action = "page", version = "" } // Parameter defaults 

Ich habe nicht die Zeit hatte, um durch die MVC Erweiterbarkeit Optionen, so habe ich mich gefragt, was die Wahlmöglichkeiten sind für dies umsetzen? Jede Probe/Beispiel wäre einfach fantastisch!

Antwort

15

Wie Sie bereits erwähnt haben, kann der Catch-All-Parameter nur am Ende einer Route angezeigt werden - der von Ihnen gepostete Code wird einen Laufzeitfehler verursachen und Ihnen den gelben Bildschirm des Todes geben, wenn Sie sogar versuchen zu laufen Ihre Bewerbung.

Es gibt mehrere Erweiterungspunkte zum Erstellen von benutzerdefinierten Routing-Szenarien. Dies sind - Route, RouteBase und IRouteHandler.

Sie können eine generierte Liste von zu bearbeitenden Routen erstellen, indem Sie RouteBase erweitern. In der Regel folgen Sie dem Muster eines Konstruktors, der eine Ressource (Controllername) aufnimmt und ihm dann eine Liste von Routen zuweist, für die er verantwortlich ist, und sie dann in Ihrem global.asax-Objekt abbildet. Hier einige Beispiel-Code Sie bauen können:

public class MyRoute : RouteBase 
{ 
    private List<Route> _routes = new List<Route>(); 

    public MyRoute(string resource) 
    { 
     // make a Resource property, not shown in this example 
     this.Resource = resource; 

     // Generate all your routes here 
     _routes.Add(
      new Route("some/url/{param1}", 
      new McvRouteHandler { 
       Defaults = new RouteValueDictionary(new { 
        controller = resource, 
        action = actionName 
       }), 
      Constraints = new RouteValueDictionary() 
     ); 
     _routes.Add(...); // another new route 
    } 

    public override RouteData GetRouteData(HttpContextBase context) 
    { 
     foreach (var route in _routes) 
     { 
      var data = route.GetRouteData(context); 
      if (data != null) 
      { 
       return data; 
      } 
     } 
     return null; 
    } 

    public override VirtualPathData GetVirtualPath(RequestContext context, RouteValueDictionary rvd) 
    { 
     foreach (var route in _routes) 
     { 
      var path = route.GetVirtualPath(context, rvd); 
      if (path != null) 
      { 
       return path; 
      } 
     } 
     return null; 
    } 
} 

Ihre Routing-Klasse zu verwenden, machen einen routes.Add(new MyRoute("page1")); in Ihrem Global.asax.

Wenn Sie noch mehr Kontrolle benötigen, können Sie eine IRouteHandler, implementieren und stattdessen MvcRouteHandlers() für Ihre Routen zu schaffen, wie im obigen Beispiel gezeigt, Ihre eigenen IRouteHandler verwenden. Dadurch können Sie die Logik des Auswählens des Controllers aus den Anforderungsdaten überschreiben.

Das gesamte Framework ist extrem erweiterbar, aber Sie müssten ziemlich viel lernen, um es richtig zu machen. Ich würde vorschlagen, einfach Ihre URLs neu zu ordnen, wenn möglich, um den Catch-All-Parameter zu nutzen, wenn Sie können.

+1

Elastic.Routing (https://github.com/lokiworld/Elastic.Routing) erweitert die integrierte MVC-Routing und bietet Ihnen die Möglichkeit zu fangen alle in jedem Segment Ihrer Route sowie einige andere gute Sachen wie optionale Segmente. – BrutalDev