Freigeben über


Single-Page-Webanwendung: KnockoutJS-Vorlage

Die Knockout-MVC-Vorlage ist Teil von ASP.NET and Web Tools 2012.2

herunterladen ASP.NET and Web Tools 2012.2

Das update ASP.NET and Web Tools 2012.2 enthält eine Single-Page Application(SPA)-Vorlage für ASP.NET MVC 4. Mit dieser Vorlage können Sie schnell mit der Erstellung interaktiver clientseitiger Web-Apps beginnen.

"Single-Page Application" (SPA) ist der allgemeine Begriff für eine Webanwendung, die eine einzelne HTML-Seite lädt und die Seite dann dynamisch aktualisiert, anstatt neue Seiten zu laden. Nach dem anfänglichen Laden der Seite spricht die SPA über AJAX-Anforderungen mit dem Server.

Diagramm mit zwei Feldern mit der Bezeichnung Client und Server. Ein Pfeil mit der Bezeichnung AJAX wechselt von Client zu Server. Ein Pfeil mit der Bezeichnung H T M L und ein Pfeil mit der Bezeichnung J SON wechseln von Server zu Client.

AJAX ist nichts Neues, aber heute gibt es JavaScript-Frameworks, die es einfacher machen, eine große anspruchsvolle SPA-Anwendung zu erstellen und zu verwalten. Außerdem erleichtern HTML 5 und CSS3 das Erstellen umfangreicher UIs.

Als Einstieg erstellt die SPA-Vorlage eine Beispielanwendung für die Aufgabenliste. In diesem Tutorial führen wir die Vorlage durch. Zunächst betrachten wir die To-Do-Listenanwendung selbst und untersuchen dann die Technologieelemente, mit denen 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 Die Option Neues Projekt aus. Oder wählen Sie im Menü Datei die Option Neu und dann Projekt aus.

Wählen Sie im Bereich Vorlagendie Option Installierte Vorlagen aus, und erweitern Sie den Knoten Visual C# . Wählen Sie unter Visual C#die Option Web aus. Wählen Sie in der Liste der Projektvorlagen ASP.NET MVC 4-Webanwendung aus. Geben Sie dem Projekt einen Namen, und klicken Sie auf OK.

Screenshot: Dialogfeld

Wählen Sie im Assistenten Neues Projektdie Option Einzelseitenanwendung aus.

Screenshot des Dialogfelds New A S P dot NET M V C 4 Project Die Einzelseitenanwendungsvorlage ist ausgewählt.

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.

Screenshot: Anmeldebildschirm

Klicken Sie auf den Link "Registrieren", und erstellen Sie einen neuen Benutzer.

Screenshot des Registrierungsbildschirms

Nach der Anmeldung erstellt die Anwendung eine Standardmäßige Aufgabenliste mit zwei Elementen. Sie können auf "Todo-Liste hinzufügen" klicken, um eine neue Liste hinzuzufügen.

Screenshot mit zwei Aufgabenlisten und der Schaltfläche

Benennen Sie die Liste um, fügen Sie der Liste Elemente hinzu, und aktivieren Sie sie. Sie können auch Elemente löschen oder eine ganze Liste löschen. Die Änderungen werden automatisch in einer Datenbank auf dem Server beibehalten (eigentlich LocalDB zu diesem Zeitpunkt, da Sie die Anwendung lokal ausführen).

Screenshot: Liste mit drei Elementen Das letzte Element wird überprüft und hat einen Durchschlag.

Architektur der SPA-Vorlage

Dieses Diagramm zeigt die Standard Bausteine für die Anwendung.

Diagramm, das die separaten Bausteine von Client und Server zeigt. Knockout dot j s, H T M L und J SON befinden sich unter Client. Ein S P dot NET M V C, A S P dot NET Web A P I, Entity Framework und Datenbank befinden sich unter Server.

Serverseitig bedient ASP.NET MVC den HTML-Code und übernimmt auch die formularbasierte Authentifizierung.

ASP.NET-Web-API verarbeitet alle Anforderungen, die sich auf die ToDoLists und ToDoItems beziehen, einschließlich Abrufen, Erstellen, Aktualisieren und Löschen. Der Client tauscht Daten mit der Web-API im JSON-Format aus.

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 verwenden Sie LocalDB für die lokale Entwicklung und stellen dann mithilfe der EF-Code-First-Migration in einer SQL-Datenbank auf dem Server bereit.

Auf der Clientseite verarbeitet die Knockout.js Bibliothek Seitenupdates von AJAX-Anforderungen. Knockout verwendet die 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 anweisen, wie die Daten präsentiert werden sollen.

Ein großer Vorteil dieser Architektur ist, dass sie die Präsentationsebene von der Anwendungslogik trennt. Sie können den Web-API-Teil erstellen, ohne etwas über das Aussehen Ihrer Webseite zu wissen. Auf der Clientseite erstellen Sie ein "Ansichtsmodell", um diese Daten darzustellen, und das Ansichtsmodell verwendet Knockout, um an den HTML-Code zu binden. Dadurch können Sie den HTML-Code ganz einfach ändern, ohne das Ansichtsmodell zu ändern. (Wir werden uns etwas später mit Knockout befassen.)

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 zu diesen kommen.)

Screenshot: Geöffneter Ordner Models

TodoItem, TodoList

Dies sind die Datenbankmodelle für Entity Framework Code First. Beachten Sie, dass diese Modelle über Eigenschaften verfügen, die auf einander verweisen. ToDoList enthält eine Auflistung von ToDoItems, und jedes ToDoItem enthält einen Verweis zurück auf seine übergeordnete ToDoList. Diese Eigenschaften werden als Navigationseigenschaften bezeichnet und stellen die 1:n-Beziehung einer To-Do-Liste und deren Aufgabenelemente dar.

Die ToDoItem -Klasse verwendet auch das Attribut [ForeignKey], 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 "Datenübertragungsobjekt". 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. Die DTO kann eine Teilmenge der Eigenschaften aus dem Domänenmodell enthalten. Sie können dies aus Sicherheitsgründen tun (um vertrauliche Daten auszublenden) oder einfach, um die Menge der gesendeten Daten zu reduzieren.
  • Um die Form der Daten zu ändern , z. B. um eine komplexere Datenstruktur zu glätten.
  • Um jegliche Geschäftslogik von der DTO (Trennung von Bedenken) fernzuhalten.
  • Wenn Ihre Domänenmodelle aus irgendeinem Grund nicht serialisiert werden können. Beispielsweise können Zirkelverweise Probleme verursachen, wenn Sie ein Objekt serialisieren Es gibt Möglichkeiten, dieses Problem in der Web-API zu behandeln (siehe Behandeln von Zirkelobjektverweise); Die Verwendung einer DTO vermeidet das Problem jedoch ganz.

In der SPA-Vorlage enthalten die DTOs dieselben Daten wie die Domänenmodelle. Sie sind jedoch weiterhin nützlich, da sie kreisförmige Verweise 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 Mitgliedschaftsdatenbank. (In diesem Fall sind die einzigen Informationen die Benutzer-ID und der Benutzername.) Die anderen Modellklassen in dieser Datei werden verwendet, um die Benutzerregistrierungs- und Anmeldeformulare zu erstellen.

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, um die Datenbank zu erstellen. Sie können EF auch mit einer vorhandenen Datenbank (Database First) verwenden.

Die TodoItemContext Klasse im Ordner Models leitet sich von DbContext ab. Diese Klasse stellt den "Klebstoff" zwischen den Modellen und EF bereit. Enthält TodoItemContext eine ToDoItem Auflistung und eine TodoList Auflistung. Um die Datenbank abzufragen, schreiben Sie einfach eine LINQ-Abfrage für diese Sammlungen. So können Sie beispielsweise alle Aufgabenlisten für Benutzer "Alice" auswählen:

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 Auflistung 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 die Web-API, um CRUD-Vorgänge für ToDoList - und ToDoItem -Instanzen zu aktivieren. Die Controller befinden sich im Ordner Controller der Lösung.

Screenshot: Geöffneter Ordner

  • TodoController: Verarbeitet HTTP-Anforderungen für To-Do-Elemente
  • TodoListController: Verarbeitet HTTP-Anforderungen für Aufgabenlisten.

Diese Namen sind wichtig, da die Web-API den URI-Pfad mit dem Controllernamen abgleicht. (Informationen dazu, wie die 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 einen einzelnen Datenmember:

private TodoItemContext db = new TodoItemContext();

Wird TodoItemContext für die Kommunikation mit EF verwendet, wie weiter oben beschrieben. Die Methoden auf dem Controller implementieren die CRUD-Vorgänge. Die Web-API ordnet HTTP-Anforderungen vom Client wie folgt den Controllermethoden zu:

HTTP-Anforderung Controller-Methode BESCHREIBUNG
GET /api/todo GetTodoLists Ruft eine Auflistung von Aufgabenlisten ab.
GET /api/todo/id GetTodoList Ruft eine Aufgabenliste nach ID ab.
PUT /api/todo/id PutTodoList Updates eine Aufgabenliste.
POST /api/todo PostTodoList Erstellt eine neue Aufgabenliste.
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. Wenn Sie beispielsweise eine To-Liste mit der ID 42 löschen möchten, lautet /api/todo/42der URI .

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 GetTodoLists -Methode 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 die ToDoList Instanzen in Instanzen zu TodoListDto konvertieren.
  • Die PUT- und POST-Methoden überprüfen den Modellzustand, bevor sie die Datenbank ändern. Wenn ModelState.IsValid false ist, geben diese Methoden HTTP 400, Bad Request zurück. Weitere Informationen zur Modellvalidierung in der Web-API finden Sie unter Modellvalidierung.
  • Die Controllerklasse wird auch mit dem Attribut [Authorize] ergänzt. 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 finden Sie unter 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 Aufgabenelemente zusammen mit jeder Aufgabenliste erhält.

MVC-Controller und -Ansichten

Die MVC-Controller befinden sich auch im Ordner Controller der Lösung. HomeControllerrendert die Standard HTML für die Anwendung. Die Ansicht für den Home-Controller 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 benutzeroberfläche Standard angezeigt. Andernfalls wird der Anmeldebereich angezeigt. Beachten Sie, dass dieses bedingte Rendering serverseitig erfolgt. Versuchen Sie niemals, vertrauliche Inhalte auf 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

Nun 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 sind die Domänendaten (ToDo-Listen und ToDo-Elemente).
  • Die Ansicht ist das HTML-Dokument.
  • Das view-model ist ein JavaScript-Objekt, das die Modelldaten enthält. Das Ansichtsmodell ist eine Code-Abstraktion 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 an das Ansichtsmodell datengebunden. Updates zum Ansichtsmodell werden automatisch in der Ansicht widergespiegelt. Bindungen funktionieren auch in der anderen 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.

Diagramm, das einen Pfeil zeigt, der von knockout punkt j s zu View Model zu Models to Data Context wechselt. Der Pfeil zwischen Knockout-Punkt j s und Ansichtsmodell ist mit Datenbindung beschriftet und zeigt auf beide Elemente.

Diese Skriptdateien befinden sich im Ordner Skripts/App der Projektmappe.

Screenshot: Unterordner mit der Bezeichnung

todo.datacontext verarbeitet alle AJAX-Aufrufe der Web-API-Controller. (Die AJAX-Aufrufe für die Anmeldung werden an anderer Stelle in ajaxlogin.js definiert.)

todo.model.js definiert die clientseitigen (Browser-)Modelle für die Aufgabenlisten. Es gibt zwei Modellklassen: todoItem und todoList.

Viele der Eigenschaften in den Modellklassen sind vom Typ "ko.observable". Observables sind, wie Knockout seine Magie macht. Aus der Knockout-Dokumentation: Ein beobachtbares ist ein "JavaScript-Objekt, das Abonnenten über Änderungen benachrichtigen kann". Wenn sich der Wert eines beobachtbaren Elements ändert, aktualisiert Knockout alle HTML-Elemente, die an diese beobachtbaren Elemente gebunden sind. TodoItem verfügt beispielsweise über Observables für die Title- und isDone-Eigenschaften:

self.title = ko.observable(data.title);
self.isDone = ko.observable(data.isDone);

Sie können auch ein beobachtbares im Code abonnieren. Beispielsweise abonniert die todoItem-Klasse Änderungen in 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);

Modell anzeigen

Das Ansichtsmodell wird in todo.viewmodel.js definiert. 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 beobachtbares Array von todoLists. Der folgende Code im Ansichtsmodell weist Knockout an, die Bindungen anzuwenden:

ko.applyBindings(window.todoApp.todoListViewModel);

HTML und Datenbindung

Der Standard HTML für die Seite ist in Views/Home/Index.cshtml definiert. Da wir die 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 Attribut "data-bind" 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(). Wenn sich dieser Wert ändert, aktualisiert Knockout das Dokument.

Knockout stellt eine Reihe verschiedener Bindungstypen bereit. Hier sind einige der Bindungen, die in der SPA-Vorlage verwendet werden:

  • foreach: Hiermit können Sie eine Schleife durchlaufen und das gleiche Markup auf jedes Element in der Liste anwenden. Dies wird verwendet, um die Aufgabenlisten und Aufgabenelemente zu rendern. Innerhalb des Foreachs werden die Bindungen auf die Elemente der Liste angewendet.
  • sichtbar: Wird verwendet, um die Sichtbarkeit umzuschalten. Ausblenden des Markups, wenn eine Sammlung leer ist, oder machen Sie die Fehlermeldung sichtbar.
  • value: Wird zum Auffüllen von Formularwerten verwendet.
  • click: Bindet ein Click-Ereignis an eine Funktion im Ansichtsmodell.

Anti-CSRF-Schutz

Cross-Site Request Forgery (CSRF) ist ein Angriff, bei dem eine böswillige Website eine Anforderung an einen anfälligen Standort sendet, auf dem der Benutzer derzeit angemeldet ist. Um CSRF-Angriffe zu verhindern, verwendet ASP.NET MVC Antifälschungstoken, auch Als Anforderungsüberprüfungstoken bezeichnet. Die Idee ist, dass der Server ein zufällig generiertes Token in eine Webseite einfügt. Wenn der Client Daten an den Server übermittelt, muss er diesen Wert in der Anforderungsnachricht enthalten.

Antifälschungstoken funktionieren, da die böswillige Seite die Token des Benutzers aufgrund von Richtlinien desselben Ursprungs nicht lesen kann. (Richtlinien des gleichen Ursprungs verhindern, dass Dokumente, die auf zwei verschiedenen Websites gehostet werden, auf die Inhalte der jeweils anderen zugreifen.)

ASP.NET MVC bietet integrierte Unterstützung für Antifälschungstoken über die AntiForgery-Klasse und das Attribut [ValidateAntiForgeryToken]. 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 Filters der Projektmappe befindet. Weitere Informationen zu Anti-CSRF in der Web-API finden Sie unter Verhindern von Cross-Site Request Forgery (CSRF)-Angriffen.

Zusammenfassung

Mit der SPA-Vorlage können Sie schnell mit dem Schreiben moderner, interaktiver Webanwendungen beginnen. Es verwendet die Knockout.js-Bibliothek, um die Präsentation (HTML-Markup) von der Daten- und Anwendungslogik zu trennen. Knockout ist jedoch nicht die einzige JavaScript-Bibliothek, die Sie zum Erstellen eines SPA verwenden können. Wenn Sie weitere Optionen erkunden möchten, sehen Sie sich die von der Community erstellten SPA-Vorlagen an.