Applicazione a pagina singola: Modello KnockoutJS
Il modello MVC Knockout fa parte di ASP.NET and Web Tools 2012.2
L'aggiornamento ASP.NET and Web Tools 2012.2 include un modello Single-Page Application (SPA) per ASP.NET MVC 4. Questo modello è progettato per iniziare a creare rapidamente app Web interattive sul lato client.
"Applicazione a pagina singola" (SPA) è il termine generale per un'applicazione Web che carica una singola pagina HTML e quindi aggiorna la pagina in modo dinamico, invece di caricare nuove pagine. Dopo il caricamento della pagina iniziale, l'applicazione a pagina singola comunica con il server tramite le richieste AJAX.
AJAX non è una novità, ma oggi sono disponibili framework JavaScript che semplificano la compilazione e la gestione di un'applicazione SPA sofisticata di grandi dimensioni. Inoltre, HTML 5 e CSS3 semplificano la creazione di interfacce utente avanzate.
Per iniziare, il modello SPA crea un'applicazione "Elenco attività" di esempio. In questa esercitazione verrà visualizzata una presentazione guidata del modello. Prima di tutto si esaminerà l'applicazione elenco attività stessa, quindi si esamineranno i componenti della tecnologia che lo rendono funzionante.
Creare un nuovo progetto modello SPA
Requisiti:
- Visual Studio 2012 o Visual Studio Express 2012 per Web
- ASP.NET aggiornamento degli strumenti Web 2012.2. È possibile installare l'aggiornamento qui.
Avviare Visual Studio e selezionare Nuovo progetto nella pagina Iniziale. In alternativa, scegliere Nuovo dal menu File e quindi Progetto.
Nel riquadro Modelli selezionare Modelli installati ed espandere il nodo Visual C# . In Visual C# selezionare Web. Nell'elenco dei modelli di progetto selezionare ASP.NET'applicazione Web MVC 4. Assegnare un nome al progetto e fare clic su OK.
Nella procedura guidata Nuovo progetto selezionare Applicazione a pagina singola.
Premere F5 per compilare ed eseguire l'applicazione. Quando l'applicazione viene eseguita per la prima volta, viene visualizzata una schermata di accesso.
Fare clic sul collegamento "Iscrizione" e creare un nuovo utente.
Dopo l'accesso, l'applicazione crea un elenco Todo predefinito con due elementi. È possibile fare clic su "Aggiungi elenco todo" per aggiungere un nuovo elenco.
Rinominare l'elenco, aggiungere elementi all'elenco e selezionarli. È anche possibile eliminare elementi o eliminare un intero elenco. Le modifiche vengono salvate automaticamente in modo permanente in un database nel server ,in realtà LocalDB a questo punto, perché l'applicazione è in esecuzione in locale.
Architettura del modello SPA
Questo diagramma mostra i blocchi predefiniti principali per l'applicazione.
Sul lato server, ASP.NET MVC gestisce il codice HTML e gestisce anche l'autenticazione basata su form.
API Web ASP.NET gestisce tutte le richieste correlate a ToDoLists e ToDoItems, tra cui recupero, creazione, aggiornamento ed eliminazione. Il client scambia i dati con l'API Web in formato JSON.
Entity Framework (EF) è il livello O/RM. Media tra il mondo orientato agli oggetti di ASP.NET e il database sottostante. Il database usa LocalDB, ma è possibile modificarlo nel file Web.config. In genere si usa LocalDB per lo sviluppo locale e quindi si esegue la distribuzione in un database SQL nel server, usando la migrazione code-first di Entity Framework.
Sul lato client, la libreria Knockout.js gestisce gli aggiornamenti delle pagine dalle richieste AJAX. Knockout usa il data binding per sincronizzare la pagina con i dati più recenti. In questo modo, non è necessario scrivere alcun codice che illustra i dati JSON e aggiorna il DOM. Al contrario, si inserisce attributi dichiarativi nel codice HTML che indicano a Knockout come presentare i dati.
Un grande vantaggio di questa architettura è che separa il livello di presentazione dalla logica dell'applicazione. È possibile creare la parte API Web senza conoscere l'aspetto della pagina Web. Sul lato client viene creato un "modello di visualizzazione" per rappresentare i dati e il modello di visualizzazione usa Knockout per eseguire l'associazione al codice HTML. In questo modo è possibile modificare facilmente il codice HTML senza modificare il modello di visualizzazione. Si esaminerà Knockout un po' più tardi.
Modelli
Nel progetto di Visual Studio la cartella Models contiene i modelli usati sul lato server. (Sono disponibili anche modelli sul lato client, che verranno visualizzati.
TodoItem, TodoList
Si tratta dei modelli di database per Entity Framework Code First. Si noti che questi modelli hanno proprietà che puntano l'una all'altra. ToDoList
contiene una raccolta di ToDoItems e ognuno ToDoItem
ha un riferimento all'elemento ToDoList padre. Queste proprietà sono denominate proprietà di navigazione e rappresentano la relazione uno-a-molti di un elenco attività e le relative attività.
La ToDoItem
classe usa anche l'attributo [ForeignKey] per specificare che ToDoListId
è una chiave esterna nella ToDoList
tabella. Indica a EF di aggiungere un vincolo di chiave esterna al database.
[ForeignKey("TodoList")]
public int TodoListId { get; set; }
public virtual TodoList TodoList { get; set; }
TodoItemDto, TodoListDto
Queste classi definiscono i dati che verranno inviati al client. "DTO" è l'acronimo di "data transfer object". L'oggetto DTO definisce la modalità di serializzazione delle entità in JSON. In generale, esistono diversi motivi per usare gli oggetti DTO:
- Per controllare le proprietà serializzate. L'oggetto DTO può contenere un subset delle proprietà del modello di dominio. Questa operazione può essere eseguita per motivi di sicurezza (per nascondere i dati sensibili) o semplicemente per ridurre la quantità di dati inviati.
- Per modificare la forma dei dati, ad esempio per rendere flat una struttura di dati più complessa.
- Per evitare qualsiasi logica di business dall'obiettivo (separazione dei problemi).
- Se i modelli di dominio non possono essere serializzati per qualche motivo. Ad esempio, i riferimenti circolari possono causare problemi quando si serializza un oggetto Esistono modi per gestire questo problema nell'API Web (vedere Gestione di riferimenti a oggetti circolari); ma l'uso di un DTO consente semplicemente di evitare del tutto il problema.
Nel modello SPA gli oggetti DTOs contengono gli stessi dati dei modelli di dominio. Tuttavia, sono ancora utili perché evitano riferimenti circolari dalle proprietà di navigazione e illustrano il modello DTO generale.
AccountModels.cs
Questo file contiene modelli per l'appartenenza al sito. La UserProfile
classe definisce lo schema per i profili utente nel database di appartenenza. In questo caso, le uniche informazioni sono l'ID utente e il nome utente. Le altre classi di modello in questo file vengono usate per creare la registrazione utente e i moduli di accesso.
Entity Framework
Il modello SPA usa EF Code First. Nello sviluppo Code First si definiscono prima i modelli nel codice e quindi Ef usa il modello per creare il database. È anche possibile usare Entity Framework con un database esistente (Database First).
La TodoItemContext
classe nella cartella Models deriva da DbContext. Questa classe fornisce la "colla" tra i modelli ed EF. Contiene TodoItemContext
una ToDoItem
raccolta e una TodoList
raccolta. Per eseguire query sul database, è sufficiente scrivere una query LINQ su queste raccolte. Ecco ad esempio come è possibile selezionare tutti gli elenchi attività per l'utente "Alice":
TodoItemContext db = new TodoItemContext();
IEnumerable<TodoList> lists =
from td in db.TodoLists where td.UserId == "Alice" select td;
È anche possibile aggiungere nuovi elementi alla raccolta, aggiornare gli elementi o eliminare elementi dalla raccolta e rendere persistenti le modifiche apportate al database.
Controller API Web ASP.NET
In API Web ASP.NET i controller sono oggetti che gestiscono le richieste HTTP. Come accennato, il modello SPA usa l'API Web per abilitare le operazioni CRUD su ToDoList
e ToDoItem
istanze. I controller si trovano nella cartella Controller della soluzione.
TodoController
: gestisce le richieste HTTP per gli elementi attivitàTodoListController
: gestisce le richieste HTTP per gli elenchi attività.
Questi nomi sono significativi perché l'API Web corrisponde al percorso URI del nome del controller. Per informazioni su come l'API Web instrada le richieste HTTP ai controller, vedere Routing in API Web ASP.NET.
Esaminiamo la ToDoListController
classe . Contiene un singolo membro dati:
private TodoItemContext db = new TodoItemContext();
viene TodoItemContext
usato per comunicare con Entity Framework, come descritto in precedenza. I metodi nel controller implementano le operazioni CRUD. L'API Web esegue il mapping delle richieste HTTP dal client ai metodi del controller, come indicato di seguito:
Richiesta HTTP | Metodo controller | Descrizione |
---|---|---|
GET /api/todo | GetTodoLists |
Ottiene una raccolta di elenchi attività. |
GET /api/todo/id | GetTodoList |
Ottiene un elenco attività in base all'ID |
PUT /api/todo/id | PutTodoList |
Aggiornamenti un elenco attività. |
POST /api/todo | PostTodoList |
Crea un nuovo elenco attività. |
DELETE /api/todo/id | DeleteTodoList |
Elimina un elenco TODO. |
Si noti che gli URI per alcune operazioni contengono segnaposto per il valore ID. Ad esempio, per eliminare un elenco con ID 42, l'URI è /api/todo/42
.
Per altre informazioni sull'uso dell'API Web per le operazioni CRUD, vedere Creazione di un'API Web che supporta operazioni CRUD. Il codice per questo controller è abbastanza semplice. Ecco alcuni punti interessanti:
- Il
GetTodoLists
metodo usa una query LINQ per filtrare i risultati in base all'ID dell'utente connesso. In questo modo, un utente vede solo i dati che appartengono a lui o a lei. Si noti inoltre che un'istruzione Select viene usata per convertire leToDoList
istanze inTodoListDto
istanze di . - I metodi PUT e POST controllano lo stato del modello prima di modificare il database. Se ModelState.IsValid è false, questi metodi restituiscono HTTP 400, Richiesta non valida. Altre informazioni sulla convalida del modello nell'API Web sono disponibili in Convalida del modello.
- La classe controller è decorata anche con l'attributo [Authorize]. Questo attributo controlla se la richiesta HTTP è autenticata. Se la richiesta non è autenticata, il client riceve HTTP 401, Non autorizzato. Per altre informazioni sull'autenticazione, vedere Autenticazione e autorizzazione in API Web ASP.NET.
La TodoController
classe è molto simile a TodoListController
. La differenza principale è che non definisce metodi GET, perché il client otterrà gli elementi attività insieme a ogni elenco attività.
Controller e viste MVC
I controller MVC si trovano anche nella cartella Controllers della soluzione. HomeController
esegue il rendering del codice HTML principale per l'applicazione. La visualizzazione per il controller Home è definita in Views/Home/Index.cshtml. La visualizzazione Home esegue il rendering di contenuto diverso a seconda che l'utente abbia eseguito l'accesso:
@if (@User.Identity.IsAuthenticated)
{
// ....
}
Quando gli utenti hanno eseguito l'accesso, visualizzano l'interfaccia utente principale. In caso contrario, viene visualizzato il pannello di accesso. Si noti che questo rendering condizionale viene eseguito sul lato server. Non tentare mai di nascondere il contenuto sensibile sul lato client. Qualsiasi elemento inviato in una risposta HTTP sia visibile a un utente che sta guardando i messaggi HTTP non elaborati.
Client-Side JavaScript e Knockout.js
A questo punto passare dal lato server dell'applicazione al client. Il modello SPA usa una combinazione di jQuery e Knockout.js per creare un'interfaccia utente interattiva senza problemi. Knockout.js è una libreria JavaScript che semplifica l'associazione del codice HTML ai dati. Knockout.js usa un modello denominato "Model-View-ViewModel".
- Il modello è costituito dai dati di dominio (elenchi ToDo ed elementi ToDo).
- La visualizzazione è il documento HTML.
- Il modello di visualizzazione è un oggetto JavaScript che contiene i dati del modello. Il modello di visualizzazione è un'astrazione del codice dell'interfaccia utente. Non ha alcuna conoscenza della rappresentazione HTML. Rappresenta invece le caratteristiche astratte della visualizzazione, ad esempio "un elenco di elementi ToDo".
La vista è associata ai dati al modello di visualizzazione. Aggiornamenti al modello di visualizzazione vengono automaticamente riflesse nella visualizzazione. Le associazioni funzionano anche l'altra direzione. Gli eventi nel DOM (ad esempio i clic) sono associati a funzioni nel modello di visualizzazione, che attivano le chiamate AJAX.
Il modello SPA organizza JavaScript sul lato client in tre livelli:
- todo.datacontext.js: invia richieste AJAX.
- todo.model.js: definisce i modelli.
- todo.viewmodel.js: definisce il modello di visualizzazione.
Questi file script si trovano nella cartella Scripts/app della soluzione.
todo.datacontext gestisce tutte le chiamate AJAX ai controller API Web. Le chiamate AJAX per l'accesso sono definite altrove, in ajaxlogin.js.
todo.model.js definisce i modelli lato client (browser) per gli elenchi attività. Sono disponibili due classi di modello: todoItem e todoList.
Molte delle proprietà nelle classi del modello sono di tipo "ko.observable". Osservabili sono come Knockout fa la sua magia. Dalla documentazione di Knockout: un osservabile è un "oggetto JavaScript in grado di notificare ai sottoscrittori le modifiche". Quando il valore di un oggetto osservabile cambia, Knockout aggiorna tutti gli elementi HTML associati a tali osservabili. Ad esempio, todoItem ha osservabili per il titolo e le proprietà isDone:
self.title = ko.observable(data.title);
self.isDone = ko.observable(data.isDone);
È anche possibile sottoscrivere un oggetto osservabile nel codice. Ad esempio, la classe todoItem sottoscrive le modifiche nelle proprietà "isDone" e "title":
saveChanges = function () {
return datacontext.saveChangedTodoItem(self);
};
// Auto-save when these properties change
self.isDone.subscribe(saveChanges);
self.title.subscribe(saveChanges);
Visualizzare il modello
Il modello di visualizzazione è definito in todo.viewmodel.js. Il modello di visualizzazione è il punto centrale in cui l'applicazione associa gli elementi della pagina HTML ai dati di dominio. Nel modello SPA il modello di visualizzazione contiene una matrice osservabile di todoLists. Il codice seguente nel modello di visualizzazione indica a Knockout di applicare le associazioni:
ko.applyBindings(window.todoApp.todoListViewModel);
HTML e data binding
Il codice HTML principale per la pagina è definito in Views/Home/Index.cshtml. Poiché si usa il data binding, il codice HTML è solo un modello per il rendering effettivo. Knockout usa associazioni dichiarative . È possibile associare elementi di pagina ai dati aggiungendo un attributo "data-bind" all'elemento . Ecco un esempio molto semplice, tratto dalla documentazione di Knockout:
<p>There are <span data-bind="text: myItems().count"></span> items<p>
In questo esempio Knockout aggiorna il contenuto dell'elemento <span> con il valore di myItems.count()
. Ogni volta che questo valore viene modificato, Knockout aggiorna il documento.
Knockout fornisce diversi tipi di associazione. Ecco alcune associazioni usate nel modello SPA:
- foreach: consente di scorrere un ciclo e di applicare lo stesso markup a ogni elemento dell'elenco. Viene usato per eseguire il rendering degli elenchi attività e degli elementi attività. All'interno dell'oggetto foreach, le associazioni vengono applicate agli elementi dell'elenco.
- visible: consente di attivare o disattivare la visibilità. Nascondere il markup quando una raccolta è vuota o rendere visibile il messaggio di errore.
- value: usato per popolare i valori del modulo.
- click: associa un evento Click a una funzione nel modello di visualizzazione.
Protezione anti-CSRF
La richiesta intersito Forgery (CSRF) è un attacco in cui un sito dannoso invia una richiesta a un sito vulnerabile in cui l'utente è attualmente connesso. Per evitare attacchi CSRF, ASP.NET MVC usa token antifalsificazione, detti anche token di verifica della richiesta. L'idea è che il server inserisce un token generato in modo casuale in una pagina Web. Quando il client invia dati al server, deve includere questo valore nel messaggio di richiesta.
I token antifalsificazione funzionano perché la pagina dannosa non è in grado di leggere i token dell'utente, a causa dei criteri di stessa origine. I criteri di stessa origine impediscono ai documenti ospitati in due siti diversi di accedere al contenuto dell'altro.
ASP.NET MVC offre il supporto predefinito per i token antifalsificazione, tramite la classe AntiForgery e l'attributo [ValidateAntiForgeryToken]. Attualmente, questa funzionalità non è incorporata nell'API Web. Tuttavia, il modello SPA include un'implementazione personalizzata per l'API Web. Questo codice è definito nella ValidateHttpAntiForgeryTokenAttribute
classe , che si trova nella cartella Filtri della soluzione. Per altre informazioni sull'anti-CSRF nell'API Web, vedere Prevenzione degli attacchi csrf (Cross-Site Request Forgery).
Conclusione
Il modello SPA è progettato per iniziare a scrivere rapidamente applicazioni Web moderne e interattive. Usa la libreria Knockout.js per separare la presentazione (markup HTML) dai dati e dalla logica dell'applicazione. Ma Knockout non è l'unica libreria JavaScript che è possibile usare per creare un'applicazione a pagina singola. Per esplorare altre opzioni, vedere i modelli spa creati dalla community.