Condividi tramite


Applicazione a pagina singola: Modello KnockoutJS

Il modello MVC Knockout fa parte di ASP.NET and Web Tools 2012.2

Scaricare 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.

Diagramma che mostra due caselle con etichetta Client e Server. Una freccia con etichetta AJAX passa da Client a Server. Una freccia con etichetta H T M L e una freccia denominata J SON passa da Server a Client.

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.

Screenshot che mostra la finestra di dialogo Nuovo progetto. Viene selezionata un'applicazione Web S P dot NET M V C 4 nell'elenco dei modelli Web.

Nella procedura guidata Nuovo progetto selezionare Applicazione a pagina singola.

Screenshot che mostra la finestra di dialogo Nuovo progetto P P dot NET M V 4. Viene selezionato il modello 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.

Screenshot che mostra la schermata di accesso My To do List.

Fare clic sul collegamento "Iscrizione" e creare un nuovo utente.

Screenshot che mostra la schermata Iscrizione.

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.

Screenshot che mostra due elenchi attività e un pulsante Aggiungi elenco attività nella parte superiore.

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.

Screenshot che mostra un elenco con tre elementi. L'ultimo elemento viene controllato e ha un barrato attraverso di esso.

Architettura del modello SPA

Questo diagramma mostra i blocchi predefiniti principali per l'applicazione.

Diagramma che mostra i blocchi predefiniti separati del client e del server. Knockout dot j s, H T M L e J SON sono in Client. Un punto S P M V C, un punto S P Web A P, Entity Framework e database sono in Server.

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.

Screenshot che mostra la cartella Models aperta.

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.

Screenshot che mostra la cartella Controllers aperta. Per fare Controller dot c s e To do List Controller dot c s sono entrambi cerchiati in rosso.

  • 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 le ToDoList istanze in TodoListDto 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.

Diagramma che mostra una freccia che va da Knockout dot j s a View Model to Models to Data Context. La freccia tra Knockout dot j s e View Model è denominata Data Binding e punta a entrambi gli elementi.

Questi file script si trovano nella cartella Scripts/app della soluzione.

Screenshot che mostra la sottocartella etichettata app aperta.

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.