Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Die Knockout MVC-Vorlage ist Teil von ASP.NET und WebTools 2012.2
Das Update ASP.NET und Webtools 2012.2 enthält eine Single-Page Application (SPA)-Vorlage für ASP.NET MVC 4. Diese Vorlage ist so konzipiert, dass Sie schnell mit dem Erstellen interaktiver clientseitiger Web-Apps beginnen können.
"Einzelseitenanwendung" (Single Page Application, SPA) ist der allgemeine Begriff für eine Webanwendung, die eine einzelne HTML-Seite lädt und dann die Seite dynamisch aktualisiert, anstatt neue Seiten zu laden. Nach dem Laden der ersten Seite spricht die SPA mit dem Server über AJAX-Anforderungen.
AJAX ist nichts Neues, aber heute gibt es JavaScript-Frameworks, die das Erstellen und Verwalten einer großen anspruchsvollen SPA-Anwendung vereinfachen. Außerdem erleichtern HTML 5 und CSS3 die Erstellung umfangreicher UIs.
Für die ersten Schritte erstellt die SPA-Vorlage eine Beispielanwendung "Aufgabenliste". In diesem Tutorial machen wir eine geführte Tour durch die Vorlage. Zunächst betrachten wir die To-do-Liste Anwendung selbst und untersuchen dann die Technologieteile, die dafür sorgen, dass sie funktioniert.
Erstellen eines neuen SPA-Vorlagenprojekts
Anforderungen:
- Visual Studio 2012 oder Visual Studio Express 2012 für Web
- ASP.NET Web Tools 2012.2-Update. Sie können das Update hier installieren.
Starten Sie Visual Studio, und wählen Sie auf der Startseite " Neues Projekt" aus. Oder wählen Sie im Menü "Datei " die Option "Neu " und dann "Projekt" aus.
Wählen Sie im Bereich "Vorlagen " die Option "Installierte Vorlagen " aus, und erweitern Sie den Knoten "Visual C# ". Wählen Sie unter Visual C#"Web" aus. Wählen Sie in der Liste der Projektvorlagen ASP.NET MVC 4-Webanwendung aus. Benennen Sie das Projekt, und klicken Sie auf 'OK'.
Wählen Sie im Assistenten " Neues Projekt " die Option "Einzelseitenanwendung" aus.
Drücken Sie F5, um die Anwendung zu erstellen und auszuführen. Wenn die Anwendung zum ersten Mal ausgeführt wird, wird ein Anmeldebildschirm angezeigt.
Klicken Sie auf den Link "Registrieren", und erstellen Sie einen neuen Benutzer.
Nachdem Sie sich angemeldet haben, erstellt die Anwendung eine Standard-Todo-Liste mit zwei Elementen. Sie können auf "Todo-Liste hinzufügen" klicken, um eine neue Liste hinzuzufügen.
Benennen Sie die Liste um, fügen Sie der Liste Elemente hinzu, und deaktivieren Sie sie. Sie können auch Elemente löschen oder eine gesamte Liste löschen. Die Änderungen werden automatisch auf einer Datenbank auf dem Server beibehalten (tatsächlich LocalDB an diesem Punkt, da Sie die Anwendung lokal ausführen).
Architektur der SPA-Vorlage
Dieses Diagramm zeigt die Wichtigsten Bausteine für die Anwendung.
Auf der Serverseite dient ASP.NET MVC dem HTML-Code und verarbeitet auch die formularbasierte Authentifizierung.
ASP.NET Web-API verarbeitet alle Anforderungen, die sich auf toDoLists und ToDoItems beziehen, einschließlich Abrufen, Erstellen, Aktualisieren und Löschen. Der Client austauscht Daten mit der Web-API im JSON-Format.
Entity Framework (EF) ist die O/RM-Ebene. Sie vermittelt zwischen der objektorientierten Welt der ASP.NET und der zugrunde liegenden Datenbank. Die Datenbank verwendet LocalDB, aber Sie können dies in der Web.config Datei ändern. In der Regel würden Sie LocalDB für die lokale Entwicklung verwenden und dann mithilfe der EF-Code-first-Migration auf einer SQL-Datenbank auf dem Server bereitstellen.
Auf der Clientseite verarbeitet die Knockout.js-Bibliothek Seitenaktualisierungen von AJAX-Anforderungen. Knockout verwendet Datenbindung, um die Seite mit den neuesten Daten zu synchronisieren. Auf diese Weise müssen Sie keinen Code schreiben, der die JSON-Daten durchläuft und das DOM aktualisiert. Stattdessen fügen Sie deklarative Attribute in den HTML-Code ein, die Knockout mitteilen, wie die Daten dargestellt werden sollen.
Ein großer Vorteil dieser Architektur besteht darin, dass sie die Präsentationsebene von der Anwendungslogik trennt. Sie können den Web-API-Teil erstellen, ohne wissen zu müssen, wie Ihre Webseite aussehen wird. Auf der Clientseite erstellen Sie ein "Ansichtsmodell", um diese Daten darzustellen, und das Ansichtsmodell verwendet Knockout, um eine Bindung an den HTML-Code herzustellen. Auf diese Weise können Sie den HTML-Code ganz einfach ändern, ohne das Ansichtsmodell zu ändern. (Wir sehen uns Knockout etwas später an.)
Modelle
Im Visual Studio-Projekt enthält der Ordner "Models" die Modelle, die auf der Serverseite verwendet werden. (Es gibt auch Modelle auf der Clientseite; wir werden darauf eingehen.)
TodoItem, TodoList
Dies sind die Datenbankmodelle für Entity Framework Code First. Beachten Sie, dass diese Modelle Eigenschaften aufweisen, die auf einander verweisen.
ToDoList enthält eine Auflistung von ToDoItems, und jeder ToDoItem verfügt über einen Verweis auf das übergeordnete ToDoList-Element. Diese Eigenschaften werden als Navigationseigenschaften bezeichnet und stellen die eins-zu-viele Beziehung einer Aufgabenliste und der zugehörigen Aufgabenelemente dar.
Die ToDoItem Klasse verwendet auch das [ForeignKey] -Attribut, um anzugeben, dass ToDoListId es sich um einen Fremdschlüssel in der ToDoList Tabelle handelt. Dadurch wird EF aufgefordert, der Datenbank eine Fremdschlüsseleinschränkung hinzuzufügen.
[ForeignKey("TodoList")]
public int TodoListId { get; set; }
public virtual TodoList TodoList { get; set; }
TodoItemDto, TodoListDto
Diese Klassen definieren die Daten, die an den Client gesendet werden. "DTO" steht für "Data Transfer Object". Der DTO definiert, wie die Entitäten in JSON serialisiert werden. Im Allgemeinen gibt es mehrere Gründe für die Verwendung von DTOs:
- Um zu steuern, welche Eigenschaften serialisiert werden. Der DTO kann eine Teilmenge der Eigenschaften aus dem Domänenmodell enthalten. Dies kann aus Sicherheitsgründen (zum Ausblenden vertraulicher Daten) oder einfach dazu führen, dass die von Ihnen gesendete Datenmenge reduziert wird.
- Um die Form der Daten zu ändern – z. B. um eine komplexere Datenstruktur zu flacheren.
- Um jede Geschäftslogik aus dem DTO herauszuhalten (Trennung von Zuständigkeiten).
- Wenn Ihre Domänenmodelle aus irgendeinem Grund nicht serialisiert werden können. Zirkelverweise können z. B. Probleme verursachen, wenn Sie ein Objekt serialisieren. Es gibt Möglichkeiten, dieses Problem in der Web-API zu behandeln (siehe Behandeln von Zirkelobjektverweise); aber die Verwendung eines DTO vermeidet einfach das Problem ganz.
In der SPA-Vorlage enthält die DTOs dieselben Daten wie die Domänenmodelle. Sie sind jedoch weiterhin nützlich, da sie Zirkelbezüge aus den Navigationseigenschaften vermeiden und das allgemeine DTO-Muster veranschaulichen.
AccountModels.cs
Diese Datei enthält Modelle für die Websitemitgliedschaft. Die UserProfile Klasse definiert das Schema für Benutzerprofile in der Mitgliedschafts-DB. (In diesem Fall sind die einzigen Informationen die Benutzer-ID und der Benutzername.) Die anderen Modellklassen in dieser Datei werden zum Erstellen der Benutzerregistrierungs- und Anmeldeformulare verwendet.
Entity Framework
Die SPA-Vorlage verwendet EF Code First. In der Code First-Entwicklung definieren Sie die Modelle zuerst im Code, und ef verwendet dann das Modell zum Erstellen der Datenbank. Sie können EF auch mit einer vorhandenen Datenbank (Datenbank zuerst) verwenden.
Die TodoItemContext Klasse im Ordner "Models" wird von DbContext abgeleitet. Diese Klasse stellt die Verbindung zwischen den Modellen und EF her. Die TodoItemContext enthält eine ToDoItem Sammlung und eine TodoList Sammlung. Um die Datenbank abzufragen, schreiben Sie einfach eine LINQ-Abfrage für diese Auflistungen. Hier erfahren Sie beispielsweise, wie Sie alle to-do Listen für Benutzer "Alice" auswählen können:
TodoItemContext db = new TodoItemContext();
IEnumerable<TodoList> lists =
from td in db.TodoLists where td.UserId == "Alice" select td;
Sie können der Sammlung auch neue Elemente hinzufügen, Elemente aktualisieren oder Elemente aus der Sammlung löschen und die Änderungen an der Datenbank beibehalten.
ASP.NET Web-API-Controller
In ASP.NET Web-API sind Controller Objekte, die HTTP-Anforderungen verarbeiten. Wie bereits erwähnt, verwendet die SPA-Vorlage Web-API, um CRUD-Vorgänge für ToDoList und ToDoItem Instanzen zu aktivieren. Die Controller befinden sich im Ordner "Controller" der Lösung.
-
TodoController: Verarbeitet HTTP-Anforderungen für to-do Elemente -
TodoListController: Behandelt HTTP-Anforderungen für to-do Listen.
Diese Namen sind wichtig, da die Web-API mit dem URI-Pfad zum Controllernamen übereinstimmt. (Informationen dazu, wie Web-API HTTP-Anforderungen an Controller weiterleitet, finden Sie unter Routing in ASP.NET Web-API.)
Sehen wir uns die ToDoListController Klasse an. Es enthält ein einzelnes Datenelement:
private TodoItemContext db = new TodoItemContext();
Dies TodoItemContext wird verwendet, um mit EF zu kommunizieren, wie weiter oben beschrieben. Die Methoden auf dem Controller implementieren die CRUD-Vorgänge. Web-API ordnet HTTP-Anforderungen vom Client zu Controllermethoden wie folgt zu:
| HTTP-Anforderung | Controller-Methode | Beschreibung |
|---|---|---|
| GET /api/todo | GetTodoLists |
Ruft eine Auflistung von to-do Listen ab. |
| GET /api/todo/id | GetTodoList |
Ruft eine To-Do-Liste nach ID ab. |
| PUT /api/todo/id | PutTodoList |
Aktualisiert eine to-do Liste. |
| POST /api/todo | PostTodoList |
Erstellt eine neue to-do Liste. |
| DELETE /api/todo/id | DeleteTodoList |
Löscht eine TODO-Liste. |
Beachten Sie, dass die URIs für einige Vorgänge Platzhalter für den ID-Wert enthalten. Um z. B. eine Aufgabenliste mit einer ID von 42 zu löschen, lautet der URI /api/todo/42.
Weitere Informationen zur Verwendung der Web-API für CRUD-Vorgänge finden Sie unter Erstellen einer Web-API, die CRUD-Vorgänge unterstützt. Der Code für diesen Controller ist ziemlich einfach. Hier sind einige interessante Punkte:
- Die
GetTodoListsMethode verwendet eine LINQ-Abfrage, um die Ergebnisse nach der ID des angemeldeten Benutzers zu filtern. Auf diese Weise sieht ein Benutzer nur die Daten, die ihm gehören. Beachten Sie außerdem, dass eine Select-Anweisung verwendet wird, um dieToDoListInstanzen inTodoListDtoInstanzen zu konvertieren. - Die PUT- und POST-Methoden überprüfen den Modellstatus, bevor Sie die Datenbank ändern. Wenn ModelState.IsValid falsch ist, geben diese Methoden HTTP 400, Bad Request zurück. Weitere Informationen zur Modellüberprüfung in der Web-API bei der Modellüberprüfung.
- Die Controllerklasse ist auch mit dem Attribut [Authorize] versehen. Dieses Attribut überprüft, ob die HTTP-Anforderung authentifiziert ist. Wenn die Anforderung nicht authentifiziert ist, empfängt der Client HTTP 401, Nicht autorisiert. Weitere Informationen zur Authentifizierung und Autorisierung in ASP.NET Web-API.
Die TodoController Klasse ist sehr ähnlich wie TodoListController. Der größte Unterschied besteht darin, dass keine GET-Methoden definiert werden, da der Client die to-do Elemente zusammen mit jeder to-do Liste erhält.
MVC-Controller und -Ansichten
Die MVC-Controller befinden sich auch im Ordner "Controller" der Lösung.
HomeController rendert den Haupt-HTML-Code für die Anwendung. Die Ansicht für den Startcontroller ist in Views/Home/Index.cshtml definiert. Die Startansicht rendert unterschiedliche Inhalte, je nachdem, ob der Benutzer angemeldet ist:
@if (@User.Identity.IsAuthenticated)
{
// ....
}
Wenn Benutzer angemeldet sind, wird die Haupt-UI angezeigt. Andernfalls wird das Login-Panel angezeigt. Beachten Sie, dass dieses bedingte Rendering auf serverseitiger Seite erfolgt. Versuchen Sie niemals, vertrauliche Inhalte auf der Clientseite auszublenden – alles, was Sie in einer HTTP-Antwort senden, ist für jemanden sichtbar, der die unformatierten HTTP-Nachrichten überwacht.
Client-Side JavaScript und Knockout.js
Jetzt wechseln wir von der Serverseite der Anwendung zum Client. Die SPA-Vorlage verwendet eine Kombination aus jQuery und Knockout.js, um eine reibungslose, interaktive Benutzeroberfläche zu erstellen. Knockout.js ist eine JavaScript-Bibliothek, die das Binden von HTML an Daten erleichtert. Knockout.js verwendet ein Muster namens "Model-View-ViewModel".
- Das Modell ist die Domänendaten (ToDo-Listen und ToDo-Elemente).
- Die Datenansicht ist das HTML-Dokument.
- Das Ansichtsmodell ist ein JavaScript-Objekt, das die Modelldaten enthält. Das Ansichtsmodell ist eine Codestraktion der Benutzeroberfläche. Sie hat keine Kenntnisse über die HTML-Darstellung. Stattdessen stellt sie abstrakte Features der Ansicht dar, z. B. "eine Liste von ToDo-Elementen".
Die Ansicht ist datengebunden an das Ansichtsmodell. Aktualisierungen des Ansichtsmodells werden automatisch in der Ansicht widergespiegelt. Bindungen funktionieren auch in die andere Richtung. Ereignisse im DOM (z. B. Klicks) sind datengebunden an Funktionen im Ansichtsmodell, die AJAX-Aufrufe auslösen.
Die SPA-Vorlage organisiert das clientseitige JavaScript in drei Ebenen:
- todo.datacontext.js: Sendet AJAX-Anforderungen.
- todo.model.js: Definiert die Modelle.
- todo.viewmodel.js: Definiert das Ansichtsmodell.
Diese Skriptdateien befinden sich im Ordner "Skripts/App" der Lösung.
todo.datacontext verarbeitet alle AJAX-Aufrufe an die Web-API-Controller. (Die AJAX-Aufrufe für die Anmeldung werden an anderer Stelle definiert, in ajaxlogin.js.)
todo.model.js definiert die clientseitigen Modelle (Browser) für die to-do-Listen. Es gibt zwei Modellklassen: todoItem und todoList.
Viele der Eigenschaften in den Modellklassen weisen den Typ "ko.observable" auf. Observables sind, wie Knockout seine Magie tut. Aus der Knockout-Dokumentation: Ein observables ist ein "JavaScript-Objekt, das Abonnenten über Änderungen benachrichtigen kann". Wenn sich der Wert eines feststellbaren Elements ändert, aktualisiert Knockout alle HTML-Elemente, die an diese Observables gebunden sind. TodoItem hat beispielsweise Observables für die Titel- und isDone-Eigenschaften:
self.title = ko.observable(data.title);
self.isDone = ko.observable(data.isDone);
Sie können im Code auch ein Observable abonnieren. Die TodoItem-Klasse abonniert beispielsweise Änderungen an den Eigenschaften "isDone" und "title":
saveChanges = function () {
return datacontext.saveChangedTodoItem(self);
};
// Auto-save when these properties change
self.isDone.subscribe(saveChanges);
self.title.subscribe(saveChanges);
Ansichtsmodell
Das Ansichtsmodell wird in todo.viewmodel.jsdefiniert. Das Ansichtsmodell ist der zentrale Punkt, an dem die Anwendung die HTML-Seitenelemente an die Domänendaten bindet. In der SPA-Vorlage enthält das Ansichtsmodell ein observierbares Array von todoLists. Der folgende Code im Ansichtsmodell weist Knockout an, die Bindungen anzuwenden:
ko.applyBindings(window.todoApp.todoListViewModel);
HTML und Datenbindung
Der Haupt-HTML-Code für die Seite wird in Views/Home/Index.cshtml definiert. Da wir Datenbindung verwenden, ist der HTML-Code nur eine Vorlage für das, was tatsächlich gerendert wird. Knockout verwendet deklarative Bindungen. Sie binden Seitenelemente an Daten, indem Sie dem Element ein "data-bind"-Attribut hinzufügen. Hier ist ein sehr einfaches Beispiel aus der Knockout-Dokumentation:
<p>There are <span data-bind="text: myItems().count"></span> items<p>
In diesem Beispiel aktualisiert Knockout den Inhalt des <Span-Elements> mit dem Wert von myItems.count(). Immer wenn dieser Wert geändert wird, aktualisiert Knockout das Dokument.
Knockout stellt eine Reihe verschiedener Bindungstypen bereit. Hier sind einige der Bindungen, die in der SPA-Vorlage verwendet werden:
- foreach: Ermöglicht es Ihnen, eine Schleife zu durchlaufen und dasselbe Markup auf jedes Element in der Liste anzuwenden. Dies wird verwendet, um die Aufgabenlisten und Aufgabenpunkte zu rendern. In der foreach-Schleife werden die Bindungen auf die Elemente der Liste angewendet.
- sichtbar: Wird zum Umschalten der Sichtbarkeit verwendet. Blenden Sie Markup aus, wenn eine Auflistung leer ist, oder machen Sie die Fehlermeldung sichtbar.
- wert: Wird zum Auffüllen von Formularwerten verwendet.
- click: Bindet ein Klickevent an eine Funktion im View-Model.
Schutz vor CSRF
Cross-Site Request Forgery (CSRF) ist ein Angriff, bei dem eine bösartige Website eine Anforderung an eine anfällige Website sendet, auf der der Benutzer derzeit angemeldet ist. Um CSRF-Angriffe zu verhindern, verwendet ASP.NET MVC Anti-Fälschungstoken, auch als Anforderungsüberprüfungstoken bezeichnet. Die Idee ist, dass der Server ein zufällig generiertes Token in eine Webseite versetzt. Wenn der Client Daten an den Server sendet, muss er diesen Wert in die Anforderungsnachricht einschließen.
Tokens zur Verhinderung von Fälschung funktionieren, da die bösartige Seite die Tokens des Benutzers aufgrund von Same-Origin-Richtlinien nicht lesen kann. (Richtlinien für den gleichen Ursprung verhindern, dass Dokumente, die auf zwei verschiedenen Websites gehostet werden, auf die Inhalte der anderen zugreifen.)
ASP.NET MVC bietet integrierte Unterstützung für Anti-Fälschungstoken über die AntiForgery-Klasse und das [ValidateAntiForgeryToken] -Attribut. Derzeit ist diese Funktionalität nicht in die Web-API integriert. Die SPA-Vorlage enthält jedoch eine benutzerdefinierte Implementierung für die Web-API. Dieser Code wird in der ValidateHttpAntiForgeryTokenAttribute Klasse definiert, die sich im Ordner "Filter" der Lösung befindet. Weitere Informationen zum Anti-CSRF in der Web-API finden Sie unter Verhindern von cross-Site Request Forgery (CSRF)-Angriffen.
Fazit
Die SPA-Vorlage ist so konzipiert, dass Sie schnell mit dem Schreiben moderner, interaktiver Webanwendungen beginnen können. Sie verwendet die Knockout.js-Bibliothek, um die Präsentation (HTML-Markup) von den Daten und der Anwendungslogik zu trennen. Knockout ist jedoch nicht die einzige JavaScript-Bibliothek, die Sie zum Erstellen eines SPA verwenden können. Wenn Sie andere Optionen erkunden möchten, sehen Sie sich die von der Community erstellten SPA-Vorlagen an.