2009-07-10 4 views
13

ho bisogno di implementare un sito MVC con gli URL per sotto percorso personalizzato:ASP.net MVC gestore/vincolo

  • category1/prodotto/1/wiki
  • category1/prodotto/2/wiki
  • categoria1/sub-category2/prodotto/3/wiki
  • category1/sub-category2/sub-Categoria3/prodotto/4/wiki
  • ecc ecc

dove il criterio di corrispondenza è che l'URL termina con "wiki".

Purtroppo il catch-all seguito funziona solo nell'ultima parte dell'URL:

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

non ho avuto il tempo di passare attraverso le opzioni di estensibilità MVC quindi mi chiedevo quali sono le scelte possibili per implementando questo? Qualsiasi esempio/esempio sarebbe semplicemente fantastico!

risposta

15

Come hai detto, il parametro catch-all può comparire solo alla fine di un percorso: il codice che hai postato genererà un errore di run-time e ti darà la schermata gialla della morte se proverai anche a correre la tua applicazione.

Esistono diversi punti di estensibilità per la creazione di scenari di routing personalizzati. Questi sono - Route, RouteBase e IRouteHandler.

È possibile creare un elenco generato di percorsi da gestire estendendo RouteBase. In genere si segue lo schema di un costruttore che accetta una risorsa (nome del controller), quindi assegna un elenco di percorsi di cui era responsabile e quindi esegue il mapping nel global.asax. Ecco qualche esempio di codice si può costruire da:

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

Per utilizzare il routing di classe, fare un routes.Add(new MyRoute("page1")); in Global.asax.

Se è necessario un ulteriore controllo, è possibile implementare un IRouteHandler e invece di creare MvcRouteHandlers() per i percorsi come illustrato nell'esempio precedente, utilizzare il proprio IRouteHandler. Ciò consentirebbe di ignorare la logica di selezione del controller dai dati della richiesta.

L'intero framework è estremamente estendibile, ma è necessario imparare un bel po 'per farlo correttamente. Ti suggerirei semplicemente di riorganizzare i tuoi URL, se possibile, per sfruttare il parametro catch-all, se possibile.

+1

Elastic.Routing (https://github.com/lokiworld/Elastic.Routing) estende l'instradamento MVC integrato e ti offre la possibilità di utilizzare il catch in qualsiasi segmento del tuo percorso, oltre ad altri buoni roba come segmenti opzionali. – BrutalDev