5

Attualmente ho una struttura di cartelle come questo:MVC Aree Routing - Cartella Regolatore con Folder

Area (folder) 
- Toolkit (folder) 
    - Controllers (folder) 
     - AdminController.cs 
    - Views (folder) 
     - Admin (folder) 
      - Privledges (folder) 
       - Create.cshtml 
       - Edit.cshtml 
       - Delete.cshtml 

che si traduce in

/Toolkit/{controller}/{action}/{tool}/{id} 

Si tratta di una cattiva pratica per impostare l'azione di comportarsi un controller simile che serve una vista basata sul parametro {tool} e parametro {id} della stringa passati all'azione?

La realizzazione di ciò di cui sto parlando:

private const string FOLDER_PRIVILEGES = "./Privileges/"; 

    public ActionResult Privileges(string tool, string id = "") 
    { 
     dynamic viewModel = null; 
     ToolViews view; // enum for the views 
     // Parse the tool name to get the enum representation of the view requested 
     bool isParsed = Enum.TryParse(tool, out view); 

     if (!isParsed) 
     { 
      return HttpNotFound(); 
     } 

     switch (view) 
     { 
      case ToolViews.Index: 
       viewModel = GetIndexViewModel(); // call a function that gets the VM 
       break; 
      case ToolViews.Edit: 
       viewModel = GetEditViewModelById(int.Parse(id)); // sloppy parse 
       break; 
      default: 
       viewModel = GetIndexViewModel(); 
       break; 
     } 
     // The folder path is needed to reach the correct view, is this bad? 
     // Should I just create a more specific controller even though it would 
     // require making about 15-20 controllers? 
     return View(FOLDER_PRIVILEGES + tool, viewModel); 
    } 

Quando scrivo una vista, devo assicurarsi che il nome del percorso viene utilizzato per la cartella

@Html.ActionLink("Edit", "./Toolkit/Admin/Priveleges/Edit", "Admin", new { id = item.id }) 

Questo sembra essere una cattiva pratica, perché se la struttura della cartella cambia, richiederà molta manutenzione.

Tuttavia, se dovessi suddividere le azioni in controller, ce ne sarebbero molte (quasi 20 con più aggiunte nel tempo).

Se quello che sto facendo è una cattiva pratica, quale sarebbe il modo migliore per servire un percorso simile?

/Toolkit/Admin/Privileges/Edit/1 

voglio evitare di nel seguente modo:

/Toolkit/Admin/CreatePrivileges/1 
/Toolkit/Admin/EditPrivileges/1 
/Toolkit/Admin/DeletePrivileges/1 

Si prega di farmi sapere se io non sto facendo alcun senso, perché io sto avendo un momento difficile mettere questa domanda in parole.

+0

Forse sto fraintendendo, ma usando il tuo modello non creerai una funzione separata per restituire il modello di visualizzazione appropriato a seconda dell'enumerazione di 'ToolViews '? L'intero punto di MVC è la convenzione sulla configurazione. Dal momento che la convenzione in MVC è un'azione separata per gestire ogni singola possibilità, sembrerebbe che sia "la migliore pratica" seguire il tuo secondo esempio. IE:/Toolkit/Admin/CreatePrivileges/1. –

+0

Ho deciso che se voglio un URL digeribile ho bisogno di scomporlo in controller più piccoli. Potrebbe essere un po 'fastidioso avere un sacco di controller, ma è meglio di quello che stavo cercando di fare prima. Invece di fare/Toolkit/Admin/CreatePrivileges/1 I have/Toolkit/Privileges/Create/1. Mi sono reso conto che la parte/Admin/non aveva importanza per l'URL una volta che avevo controller multipli e più piccoli. –

+0

Quindi penso che siamo d'accordo? –

risposta

1

Penso che tu stia cercando di forzare una convenzione in MVC che va contro il suo intento originale.

Con MVC, il controller è un nome e la tua azione è un verbo. Usando le esempi, si dispone:

  • Toolkit (sostantivo) - Area
    • Admin (? Sostantivo) - Sottozona? < - questo è quello che è un po 'eccentrico
      • privilegi (sostantivo) - Controllore
        • Create (verbo) - Azione
        • Edit (verbo) - Azione
        • Delete (verbo) - Azione

Quindi, come puoi vedere, se puoi considerare Toolkit + Admin come area + sottoarea, o combinarli in un'unica area (TookitAdmin), ti riconduce allo scopo originale per i controller e le azioni.

In base ai commenti, sembra che tu abbia deciso di andare in questo modo. Ma volevo sottolineare che la conclusione a cui sei giunto in un round round è tornare alle radici di MVC.

Come nota a margine, hai preso in considerazione il passaggio a MVC4? Il suo Web API fornisce un supporto migliore per un'API RESTful, che sembra si stia tentando di ottenere.

+0

Sono d'accordo. Ero strana usando tanti controller. Soprattutto i controller con una sola azione. Tuttavia, dopo aver provato questo approccio, non è stato così male quando si trova nella propria area. Ho usato le API Web e quell'esperienza è ciò che mi fa desiderare un URL più RESTful. Purtroppo, questo progetto è bloccato in MVC3 per il momento. –

1

Non una risposta alla domanda originale, ma l'OP ha richiesto un campione di un vincolo Enum piuttosto che dover controllare l'enum in ogni azione. vale a dire:

// Parse the tool name to get the enum representation of the view requested 
bool isParsed = Enum.TryParse(tool, out view); 

if (!isParsed) 
{ 
    return HttpNotFound(); 
} 

Invece di dover accettare il valore enum (Tool, in questo caso) come una stringa, è possibile forzare il valore di entrare nella vostra azione già lanciato come l'enum appropriata. Un ulteriore vantaggio è che il framework MVC si prenderà cura di restituire la risposta corretta (HttpNotFound) in questo caso.

Questo è il metodo di vincolo. Accetta qualsiasi tipo di Enum. Non è necessario creare un vincolo separato per ogni Enum.

public class EnumConstraint<T> : IRouteConstraint where T : struct 
{ 
    private readonly HashSet<string> enumNames; 
    public EnumConstraint() 
    { 
     string[] names = Enum.GetNames(typeof(T)); 
     this.enumNames = new HashSet<string>(from name in names select name.ToLowerInvariant()); 
    } 

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) 
    { 
     return this.enumNames.Contains(values[parameterName].ToString().ToLowerInvariant()); 
    } 

} 

Poi, nel metodo RegisterRoutes (MVC4) o la pagina global.asax.cs (MVC3), è sufficiente registrare il proprio percorso in questo modo:

routes.MapRoute(
    url: "/Toolkit/Admin/{Action}/{id}", 
    constraints: new { Action = new EnumConstraint<ToolViews>(), id = @"\d+" } 
); 

Ho anche aggiunto un vincolo numero sul id per salvare anche l'analisi.

Fammi sapere come funziona.

+0

Ciò è estremamente utile. Grazie mille! –

+0

@David - Felice di aiutare –