ASP.NET MVC: come utilizzare esattamente i modelli di visualizzazione

Diciamo che ho una pagina che consente la modifica dei dettagli di un utente, quindi ho un ViewModel come questo:

public class UserViewModel { public string Username { get; set; } public string Password { get; set; } public int ManagerId { get; set; } public string Category { get; set; } } 

Quindi, sulla mia azione EditUser posso avere questo passato dal modello di modello e quindi posso mapparlo al modello di dominio:

 public ActionResult EditUser(UserViewModel user) { ... 

Tuttavia, la pagina che visualizza il modulo necessita anche di dettagli come un elenco di Manager e Categorie per fornire i menu a discesa per tali campi. Potrebbe anche visualizzare un elenco di altri utenti in una barra laterale in modo da poter passare da un utente all’altro che stai modificando.

Quindi ho un altro modello di vista:

 public class ViewUserViewModel { public UserViewModel EditingUser { get; set; } public IEnumerable Managers { get; set; } public IEnumerable Categories { get; set; } public IEnumerable AllUsers { get; set; } } 

È questo il modo corretto per farlo? Sono entrambi i modelli di vista? Se è così, c’è una convenzione di denominazione che dovrei usare in modo da poter distinguere tra VM che sono come i modelli e VM che contengono solo dati per la pagina?

Ho sbagliato tutto questo?

Come faccio questo in una scorciatoia:

  1. Crea una class ViewModel separata per ogni modulo sulla pagina, quindi eseguo il rendering di queste classi con PartialViews come @{Html.RenderPartial("PartialName", Model.PartialModel);} .
  2. Se la pagina contiene cose come metam html, creo una class separata per i meta e la metto in sezione nella pagina.
  3. Casi di rest come “dovrei metterlo in una class separata?” è il tuo giudizio.

Quindi ad esempio hai una pagina che ha qualche tipo di login / barra di registrazione o popup qualunque.

 public class SomePageViewModel { public RegisterBarVM Register { get; set; } public LoginBarVM LoginBar { get; set; } public MetasVM Metas { get; set; } public string MaybePageTitle { get; set;} public string MaybePageContent { get; set;} [HiddenInput(DisplayValue = false)] public int IdIfNeeded { get; set; } public IEnumerable SomeItems {get; set;} public string PickedItemId { get;set; } } public class RegisterBarVM { public string RegisterUsername {get;set;} public string RegisterPassword {get;set;} //... } public class LoginBarVM { public string LoginUserame {get;set;} public string LoginPassword {get;set;} //... } //cshtml @model yourClassesNamespace.SomePageViewModel @{ Html.RenderPartial("LoginBar", Model.LoginBar); //form inside Html.RenderPartial("RegisterBar", Model.RegisterBar); //form inside using(Html.BeginForm()) { @Html.EditorFor(m => m.IdIfNeeded) @Hmtl.EditorFor(m => m.MaybePageTitle) @Hmtl.EditorFor(m => m.MaybePageContent) @Hmtl.DropDownListFor(m => m.PickedItemId, new SelectList(Model.SomeItems))  } } @section Metas { @{Html.RenderPartial("Meatas", Model.Metas} } 

Informazioni sui modelli di editor Brad Wilsons Blog e solo su google o cercare le risorse di stack sui template display / editor e HtmlHelpers. Sono tutti molto utili per creare siti Web coerenti.

“Visualizza modello” è solo uno schema. Non c’è nulla di magico nel nome, ma in generale qualsiasi class passata a una vista (sia per la semplice visualizzazione di dati o ai fini di invio di moduli) viene indicata come “modello di vista” e ha un nome come FooViewModel o FooVM per indicare che fa parte di quel modello di “modello di vista”.

Non voglio diventare troppo filosofico con te, ma penso che sarà utile un po ‘di riferimento sugli schemi in gioco. ASP.NET MVC ovviamente incoraggia un modello architettonico MVC (Model-View-Controller). In MVC il modello è il contenitore per tutte le logiche di business dell’applicazione. Il Controller è responsabile della gestione della richiesta, del recupero del modello, del rendering della Vista con quel modello e della restituzione di una risposta. Sembra una grande responsabilità, ma in realtà il framework gestisce la maggior parte di questo dietro le quinte, quindi i Controller sono tipicamente (e dovrebbero essere) molto chiari sul codice. Sono responsabili della minima quantità di funzionalità per colbind tutto. Infine, la vista è responsabile della creazione del livello dell’interfaccia utente che consente all’utente di interagire con i dati nel modello. Non è responsabile per i dati stessi, né dovrebbe essere (ViewData / ViewBag è una violazione piuttosto grande qui, almeno in quanto viene utilizzato dagli sviluppatori nella pratica).

Quindi, ciò significa che la maggior parte della logica dell’applicazione dovrebbe essere presente nel modello, e in genere è una buona cosa. Tuttavia, poiché il modello è il paradiso dei dati dell’applicazione, generalmente viene mantenuto in un database o simile. Ciò crea un conflitto di interessi poiché ora è necessario avviare un atto di bilanciamento tra i dati che devono essere mantenuti e quali dati dovrebbero esistere solo ai fini della visualizzazione.

È qui che entrano in gioco i modelli di visualizzazione. MVVM (Model-View-View Model), un modello un po ‘parallelo a MVC, riconosce i problemi inerenti in un approccio one-model-to-rule-them-all. Non entrerò nei dettagli qui, perché MVC non usa questo modello. Tuttavia, molti sviluppatori di ASP.NET MVC hanno cooptato il View Model di MVVM. Ciò che essenzialmente si ottiene è un’ quadro supportata da database (il modello tradizionale) e quindi solitamente molti diversi modelli di vista che rappresentano quell’ quadro in vari stati. Ciò consente al modello di contenere la logica aziendale pertinente alla persistenza mentre i modelli di visualizzazione contengono la logica aziendale pertinente alla visualizzazione, alla creazione e all’aggiornamento del modello.

Sono andato fuori pista un po ‘, ma il lungo e corto è che quello che stai facendo è perfettamente accettabile. In effetti, è una buona pratica. Crea tutti i modelli di visualizzazione richiesti dall’applicazione e utilizzali per archiviare effettivamente i dati e la logica di business necessari per le tue visualizzazioni. (Questo include cose come SelectList s. Né il tuo controller né la vista dovrebbero avere bisogno di sapere come creare una SelectList per un menu a discesa.)

Personalmente preferisco mettere tutte le informazioni necessarie per il rendering della pagina nel ViewModel, in quanto tale è lo scopo del ViewModel – per fornire tutti i dati per la vista. Quindi il mio UserViewModel conterrebbe proprietà per Managers , Categories e AllUsers e il controller riempie tali raccolte prima di passare ViewModel alla vista.

Questo è essenzialmente ciò che hai fatto – rimuove solo il ViewModel extra dall’equazione.

Ho anche visto altri programmatori utilizzare ViewData per inviare gli elenchi a discesa alla vista, ma non mi piace perché ViewData non è fortemente digitato, mentre un ViewModel lo è.