Visualizzazione post con etichetta ASP.NET MVC. Mostra tutti i post
Visualizzazione post con etichetta ASP.NET MVC. Mostra tutti i post

martedì 14 febbraio 2012

Domain Model o View Model?

Per quanti di voi hanno studiato e utilizzano ASP.NET MVC o comunque qualsiasi altro framework basato sul pattern MVC, saprà benissimo cosa si intende per Model, View e Controller.
Bene, se per view e controller generalmente non si hanno dubbi nell'implementazione pratica, per il model è possibile farsi qualche domanda in più.

Devo usare le mie classi di dominio? In molti libri di ASP.NET MVC o quasi in tutti gli esempi in giro per la rete, troverete la solita classe Product o User che viene utilizzata nel controller e passata tranquillamente alla view. Niente di più facile, no?

Ma sarà sempre così? Beh la risposta è...quasi mai!
Basta passare dall'esempio alla prima pagina "reale", per capire subito che le classi da utilizzare nella view non possono essere quelle di dominio. Ecco alcune motivazioni:

  • E' quasi matematicamente certo che una pagina web non contenga dati di una solo classe di dominio. Banalmente se stai creando la pagina di edit del tuo caro oggetto Product e una delle sue proprietà deve essere selezionata da una tendina, dove passo alla view gli item dell'elenco?
  • Può capitare che esistano delle regole di validazione diverse a seconda della view in questione. Queste dunque non possono essere definite tramite il solo meccanismo di validazione tramite attributi delle classi di dominio
  • Capiterà facilmente che la view dovrà gestire solo alcune delle proprietà della classe di dominio. Perchè dunque dovrei fare il bind dei dati con l'intera classe Product, andando magari incontro a problemi di sicurezza nel caso ci fosserò proprietà che non possono essere editati dall'utente? Un utente malintenzionato potrebbe infatti iniettarvi anche queste proprietà in post. E' vero che si può sempre definire a livello di action quali proprietà far gestire o meno dal binder, ma è necessaria una configurazione in più e sopratutto ricordarsi di farla:)

In conclusione, difficilmente le vostre classi di dominio potranno essere passate direttamente alla view, bensì nella quasi totalità dei casi sarà necessario crearsi delle classi ad-hoc (View Model) con le sole informazione che interessano alla view e che vengono poi gestite da essa stessa.

E' innegabile che ciò è un'attività dispendiosa in tempo, ma esistono alcuni progetti interessanti che possono venire in aiuto, come AutoMapper (http://automapper.org) che ti permette di mappare automaticamente le classi del View Model con quelle del Domain model.


mercoledì 3 marzo 2010

Mantenere lo stato dei controlli in ASP.NET MVC

Una delle prime cose che si imparano quando si affronta per la prima volta il mondo di ASP.NET MVC provenendo da un'esperienza di WebForms, è che la grande "invenzione" che ha reso tanto popolare quest'ultima tecnologia non esiste più, ossia il ViewState.

Dopo un momento di smarrimento, si cerca di capire come farne a meno (e capirete che di vantaggi ce ne sono!)

Ovviamente i creatori di MVC non ci hanno lasciato con le mani vuote, ma hanno pensato a un modo articolato ma efficace per ottenere lo stesso risultato. In realtà quello che si può ottenere "gratis" dal framework è il mantenimento del valore effettivo di un input control (dunque non le altre proprietà come Visible, Color, ecc..)

Prendiamo ad esempio una textbox:

<%= Html.TextBox("SearchText","testo di default")%>

e il seguente Action method invocato dal submit presente nella pagina della textbox:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Search(string SearchText)
{
    return View();
}

Mandando in esecuzione il codice vedremo che alla prima apertura della pagina la textbox avrà il valore "testo di default", modificando la textbox e premendo il bottone di submit la textbox viene renderizzata con il valore modificato. La textbox ha mantenuto lo stato!

Cosa è successo??

Tutto ciò è dovuto al fatto che "per convenzione" il framework MVC valorizza i controlli presenti in una pagina prendendone i valori secondo una scala di priorità di seguito riportata:

1 MVC controlla se è presente un valore nella proprietà ModelState["SearchText"].Value.AttemptedValue.   ModelState è una collection in cui sono aggiunti TUTTI i valori che i model binder trasferiscono al controller. La collection diventa utile quando si vuole far apparire un messaggio di errore di validazione e non si vuole perdere al post della pagina quello che l'utente ha inserito.

2 MVC controlla se è presente un valore di default del controllo (nel nostro caso la stringa "testo di default")

3 MVC controlla se è presente un valore per l'elemento ViewData["SearchText"]. ViewData è la collection che il Controller passa alla View con tutti i dati sul modello.

4 MVC controlla se è presente un valore per l'elemento ViewData.Model.SearchText . ViewData.Model è l'oggetto che viene passato dal Controller alla View come modello

Tornando al nostro caso, al primo accesso della pagina scatta la regola 2. Il ModelState, infatti, è vuoto mentre la stringa di default è valorizzata.
Al post della pagina, il "miracolo" è possibile proprio per la presenza della proprietà ModelState["SearchText"].Value.AttemptedValue (regola 1). Notare che questa è stata valorizzata poichè la proprietà SearchText è un parametro di ingresso dell'action method e dunque è stata inserita nel ModelState dal model binder. Qualora non ci fosse tale parametro, il ModelState["SearchText"] non sarebbe valorizzato e noi al post della pagina troveremmo di nuovo la stringa "testo di default" (di nuovo regola 2).

E' bene dunque tenere sempre a mente queste priorità in modo da non incorrere in comportamenti non previsti.