2009-06-30 5 views
5

Ho il seguente caso in cui voglio accettare le seguenti rotteasp.net MVC - Itinerari per stringa o int (es/tipo/23 o/tipo/cappelli)

'/type/view/23' or '/type/view/hats' 

dove 23 è l'ID per i cappelli.

Il controller simile a questa:

public class TypeController 
{ 
    [AcceptVerbs(HttpVerbs.Get)] 
    public ActionResult View(int id) 
    { 
     ... 
    } 
} 

Ora se passano in 23 senza problemi. Se passano in cappelli, ho del lavoro da fare. Ora mi stavo chiedendo in questo caso avrei tradotto i cappelli a 23 usando un ActionFilter che cerca di vedere se il valore è passato mentre l'id è un int (se è così verifica che esista nel database) o se è una stringa sembra sul database per quale sia l'id della stringa che è stata passata. In entrambi i casi, se non viene trovata una corrispondenza, vorrei reindirizzare l'utente a un'azione diversa.

In primo luogo è l'approccio che ho chiamato corretto, in secondo luogo è possibile eseguire un reindirizzamento all'interno di un filtro di azione.

Acclamazioni Anthony

risposta

4

Modificare la firma per accettare una stringa. Quindi controlla se il valore di id è un int. Se lo è, cerca quindi id, se non cerca per nome. Se non trovi una corrispondenza, esegui il tuo reindirizzamento.

public class TypeController 
{ 
    [AcceptVerbs(HttpVerbs.Get)] 
    public ActionResult View(string id) 
    { 
     Product product = null; 
     int productID = -1; 
     if (int.TryParse(id, out productID)) 
     { 
      product = db.Products 
         .Where(p => p.ID == productID) 
         .SingleOrDefault(); 
     } 
     else 
     { 
      product = db.Products 
         .Where(p => p.Name == id) 
         .SingleOrDefault(); 
     } 

     if (product == null) 
     { 
      return RedirectToAction("Error"); 
     } 
     ... 
    } 
} 

La ragione per cui vorrei fare è che, al fine di sapere quale controller/azioni da applicare, il quadro è andare a cercare uno che corrisponda alla firma dei dati percorso che è passato. Se don 't avere una firma che corrisponde - in questo caso uno che prende una stringa - otterrai un'eccezione prima che qualcuno dei tuoi filtri sia invocato. Sfortunatamente, non penso che tu possa averne uno che prende una stringa e un altro che prende un int - in quel caso il framework non sarà in grado di dire quale debba corrispondere se viene passato un singolo parametro, almeno se è un numero, cioè. Rendendolo un parametro stringa e gestendo la traduzione da soli, si consente al framework di svolgere il proprio lavoro e si ottiene il comportamento desiderato: non è necessario alcun filtro.

+1

Pensando di trovare un modo per il quadro per fare il lavoro, potrei avere due rotte come la seguente: this._Routes.MapRoute ("TypeInt" , "type/view/{id}", new {controller = "Type", action = "ViewInt"}, new {page = @ "^ \ d + $"}); this._Routes.MapRoute ("TypeString", "type/view/{id}", new {controller = "Type", action = "ViewString"}); Ne varrebbe la pena farlo? o pensi solo di provare? –

+0

Non vedo ciò che guadagni aggiungendo complicazioni all'infrastruttura di routing, tranne che fa il parsing per te. Non sono abbastanza intelligente per sapere se funzionerebbe senza testarlo veramente.Personalmente, probabilmente avrei due diverse azioni View e ViewByName, che usano entrambi lo stesso metodo privato per generare i dati una volta trovato il prodotto corretto. Per me sarebbe ancora più semplice e chiaro. – tvanfosson

0

Incerti si può fare questo. Penserei che avresti bisogno di passare una stringa e poi controllare se è numerico, ma potrebbe esserci un modo migliore.

Per quanto riguarda il reindirizzamento uso

return RedirectToAction("MyProfile", "Profile"); 

È possibile passare valori di percorso, come parte della chiamata RedirectToAction in modo da poter passare in id o nomi, ecc, se questo è ciò che è necessario.

Ci sono altri come il reindirizzamento a percorsi che possono anche essere utili per quello che vuoi.

+0

Con il reindirizzamento pensavo di fare questo dall'interno del ActionFilter –