Aplikacja jednostronicowa: szablon KnockoutJS
Szablon Knockout MVC jest częścią ASP.NET and Web Tools 2012.2
Aktualizacja ASP.NET and Web Tools 2012.2 zawiera szablon aplikacji Single-Page (SPA) dla ASP.NET MVC 4. Ten szablon został zaprojektowany w celu szybkiego rozpoczęcia tworzenia interaktywnych aplikacji internetowych po stronie klienta.
"Aplikacja jednostronicowa" (SPA) to ogólny termin dla aplikacji internetowej, która ładuje pojedynczą stronę HTML, a następnie aktualizuje stronę dynamicznie, zamiast ładować nowe strony. Po początkowym załadowaniu strony SPA rozmawia z serwerem za pośrednictwem żądań AJAX.
AJAX nie jest niczym nowym, ale obecnie istnieją struktury JavaScript, które ułatwiają tworzenie i konserwację dużej wyrafinowanej aplikacji SPA. Ponadto języki HTML 5 i CSS3 ułatwiają tworzenie rozbudowanych interfejsów użytkownika.
Aby rozpocząć pracę, szablon SPA tworzy przykładową aplikację "Lista zadań do wykonania". W tym samouczku przedstawimy przewodnik po szablonie. Najpierw przyjrzymy się samej aplikacji listy zadań do wykonania, a następnie przeanalizujemy elementy technologiczne, które sprawiają, że działają.
Tworzenie nowego projektu szablonu SPA
Wymagania:
- Visual Studio 2012 lub Visual Studio Express 2012 for Web
- ASP.NET aktualizacja narzędzi Web Tools 2012.2. Aktualizację można zainstalować tutaj.
Uruchom program Visual Studio i wybierz pozycję Nowy projekt na stronie Start. Ewentualnie w menu Plik wybierz pozycję Nowy , a następnie pozycję Projekt.
W okienku Szablony wybierz pozycję Zainstalowane szablony i rozwiń węzeł Visual C# . W obszarze Visual C# wybierz pozycję Sieć Web. Na liście szablonów projektów wybierz pozycję ASP.NET aplikacja internetowa MVC 4. Nadaj projektowi nazwę i kliknij przycisk OK.
W kreatorze Nowy projekt wybierz pozycję Aplikacja jednostronicowa.
Naciśnij klawisz F5, aby skompilować i uruchomić aplikację. Po pierwszym uruchomieniu aplikacji zostanie wyświetlony ekran logowania.
Kliknij link "Zarejestruj się" i utwórz nowego użytkownika.
Po zalogowaniu aplikacja tworzy domyślną listę zadań do wykonania z dwoma elementami. Możesz kliknąć pozycję "Dodaj listę zadań do wykonania", aby dodać nową listę.
Zmień nazwę listy, dodaj elementy do listy i zaznacz je. Możesz również usunąć elementy lub usunąć całą listę. Zmiany są automatycznie utrwalane w bazie danych na serwerze (w rzeczywistości localDB w tym momencie, ponieważ aplikacja jest uruchomiona lokalnie).
Architektura szablonu SPA
Na tym diagramie przedstawiono główne bloki konstrukcyjne aplikacji.
Po stronie serwera ASP.NET MVC obsługuje kod HTML, a także obsługuje uwierzytelnianie oparte na formularzach.
ASP.NET internetowy interfejs API obsługuje wszystkie żądania związane z listami ToDoList i ToDoItems, w tym pobieranie, tworzenie, aktualizowanie i usuwanie. Klient wymienia dane za pomocą internetowego interfejsu API w formacie JSON.
Program Entity Framework (EF) to warstwa O/RM. Pośredniczy między obiektowym światem ASP.NET a bazową bazą danych. Baza danych używa bazy danych LocalDB, ale można to zmienić w pliku Web.config. Zazwyczaj do programowania lokalnego należy używać bazy danych LocalDB, a następnie wdrażać je w bazie danych SQL na serwerze przy użyciu migracji najpierw kodu EF.
Po stronie klienta biblioteka Knockout.js obsługuje aktualizacje stron z żądań AJAX. Knockout używa powiązania danych, aby zsynchronizować stronę z najnowszymi danymi. W ten sposób nie trzeba pisać żadnego kodu, który przechodzi przez dane JSON i aktualizuje dom. Zamiast tego należy umieścić atrybuty deklaratywne w kodzie HTML, które informują Knockout, jak przedstawić dane.
Wielką zaletą tej architektury jest oddzielenie warstwy prezentacji od logiki aplikacji. Część internetowego interfejsu API można utworzyć bez znajomości sposobu wyglądu strony internetowej. Po stronie klienta utworzysz "model widoku", aby przedstawić te dane, a model widoku używa platformy Knockout do powiązania z kodem HTML. Umożliwia to łatwą zmianę kodu HTML bez zmiany modelu widoku. (Przyjrzymy się Knockout nieco później).
Modele
W projekcie programu Visual Studio folder Models zawiera modele używane po stronie serwera. (Istnieją również modele po stronie klienta; do nich dojdziemy).
TodoItem, TodoList
Są to modele baz danych dla programu Entity Framework Code First. Zwróć uwagę, że te modele mają właściwości wskazujące siebie nawzajem. ToDoList
Zawiera kolekcję ToDoItems, a każda z nich ToDoItem
zawiera odwołanie do nadrzędnej listy zadań DoDoList. Te właściwości są nazywane właściwościami nawigacji i reprezentują relację jeden do wielu z listą zadań do wykonania i jej elementami do wykonania.
Klasa ToDoItem
używa również atrybutu [ForeignKey], aby określić, że ToDoListId
jest to klucz obcy w ToDoList
tabeli. Dzięki temu platforma EF doda ograniczenie klucza obcego do bazy danych.
[ForeignKey("TodoList")]
public int TodoListId { get; set; }
public virtual TodoList TodoList { get; set; }
TodoItemDto, TodoListDto
Te klasy definiują dane, które będą wysyłane do klienta. "DTO" oznacza "obiekt transferu danych". Obiekt DTO definiuje sposób serializacji jednostek w formacie JSON. Ogólnie rzecz biorąc, istnieje kilka powodów, dla których należy używać obiektów DTO:
- Aby kontrolować, które właściwości są serializowane. Obiekt DTO może zawierać podzbiór właściwości z modelu domeny. Możesz to zrobić ze względów bezpieczeństwa (aby ukryć poufne dane) lub po prostu zmniejszyć ilość wysyłanych danych.
- Aby zmienić kształt danych , np. w celu spłaszczenia bardziej złożonej struktury danych.
- Aby zachować wszelką logikę biznesową poza celami DTO (separacja problemów).
- Jeśli z jakiegoś powodu nie można serializować modeli domeny. Na przykład odwołania cykliczne mogą powodować problemy podczas serializacji obiektu Istnieją sposoby obsługi tego problemu w internetowym interfejsie API (zobacz Obsługa odwołań do obiektów cyklicznych); ale korzystanie z DTO po prostu unika problemu całkowicie.
W szablonie SPA obiekty DTO zawierają te same dane co modele domeny. Są one jednak nadal przydatne, ponieważ unikają odwołań cyklicznych z właściwości nawigacji i przedstawiają ogólny wzorzec DTO.
AccountModels.cs
Ten plik zawiera modele członkostwa w witrynie. Klasa UserProfile
definiuje schemat profilów użytkowników w bazie danych członkostwa. (W tym przypadku jedynymi informacjami są identyfikator użytkownika i nazwa użytkownika). Inne klasy modeli w tym pliku są używane do tworzenia formularzy rejestracji i logowania użytkownika.
Entity Framework
Szablon SPA używa EF Code First. W programowania Code First należy najpierw zdefiniować modele w kodzie, a następnie program EF używa modelu do utworzenia bazy danych. Możesz również użyć programu EF z istniejącą bazą danych (Database First).
Klasa TodoItemContext
w folderze Models pochodzi z obiektu DbContext. Ta klasa zapewnia "klej" między modelami a ef. Obiekt TodoItemContext
zawiera ToDoItem
kolekcję i TodoList
kolekcję. Aby wykonać zapytanie dotyczące bazy danych, wystarczy napisać zapytanie LINQ względem tych kolekcji. Na przykład poniżej przedstawiono sposób wybierania wszystkich list czynności do wykonania dla użytkownika "Alice":
TodoItemContext db = new TodoItemContext();
IEnumerable<TodoList> lists =
from td in db.TodoLists where td.UserId == "Alice" select td;
Możesz również dodawać nowe elementy do kolekcji, aktualizować elementy lub usuwać elementy z kolekcji i utrwalać zmiany w bazie danych.
kontrolery internetowego interfejsu API ASP.NET
W ASP.NET internetowym interfejsie API kontrolery są obiektami obsługującymi żądania HTTP. Jak wspomniano, szablon SPA używa internetowego interfejsu API do włączania operacji CRUD na ToDoList
wystąpieniach i ToDoItem
. Kontrolery znajdują się w folderze Kontrolery rozwiązania.
TodoController
: obsługuje żądania HTTP dla elementów do wykonaniaTodoListController
: obsługuje żądania HTTP dla list do wykonania.
Te nazwy są znaczące, ponieważ internetowy interfejs API jest zgodny ze ścieżką identyfikatora URI do nazwy kontrolera. (Aby dowiedzieć się, jak internetowy interfejs API kieruje żądania HTTP do kontrolerów, zobacz Routing w interfejsie API sieci Web ASP.NET).
Przyjrzyjmy ToDoListController
się klasie. Zawiera on jeden element członkowski danych:
private TodoItemContext db = new TodoItemContext();
Element służy do komunikowania TodoItemContext
się z platformą EF zgodnie z wcześniejszym opisem. Metody na kontrolerze implementują operacje CRUD. Internetowy interfejs API mapuje żądania HTTP z klienta na metody kontrolera w następujący sposób:
Żądanie HTTP | Controller, metoda | Opis |
---|---|---|
GET /api/todo | GetTodoLists |
Pobiera kolekcję list zadań do wykonania. |
GET /api/todo/id | GetTodoList |
Pobiera listę zadań do wykonania według identyfikatora |
PUT /api/todo/id | PutTodoList |
Aktualizacje listę zadań do wykonania. |
POST /api/todo | PostTodoList |
Tworzy nową listę zadań do wykonania. |
DELETE /api/todo/id | DeleteTodoList |
Usuwa listę zadań do wykonania. |
Zwróć uwagę, że identyfikatory URI niektórych operacji zawierają symbole zastępcze wartości identyfikatora. Aby na przykład usunąć listę zadań z identyfikatorem 42, identyfikator URI to /api/todo/42
.
Aby dowiedzieć się więcej na temat korzystania z internetowego interfejsu API dla operacji CRUD, zobacz Tworzenie internetowego interfejsu API obsługującego operacje CRUD. Kod dla tego kontrolera jest dość prosty. Oto kilka interesujących kwestii:
- Metoda
GetTodoLists
używa zapytania LINQ do filtrowania wyników według identyfikatora zalogowanego użytkownika. W ten sposób użytkownik widzi tylko dane, które należą do niego. Zwróć również uwagę, że instrukcja Select służy do konwertowaniaToDoList
wystąpień naTodoListDto
wystąpienia. - Metody PUT i POST sprawdzają stan modelu przed zmodyfikowaniem bazy danych. Jeśli wartość ModelState.IsValid jest fałszywa, te metody zwracają http 400, nieprawidłowe żądanie. Przeczytaj więcej na temat walidacji modelu w internetowym interfejsie API na stronie Walidacja modelu.
- Klasa kontrolera jest również ozdobiona atrybutem [Autoryzuj]. Ten atrybut sprawdza, czy żądanie HTTP jest uwierzytelniane. Jeśli żądanie nie zostanie uwierzytelnione, klient otrzyma protokół HTTP 401, Brak autoryzacji. Przeczytaj więcej na temat uwierzytelniania w temacie Uwierzytelnianie i autoryzacja w ASP.NET internetowym interfejsie API.
Klasa jest bardzo podobna TodoController
do TodoListController
klasy . Największą różnicą jest to, że nie definiuje żadnych metod GET, ponieważ klient uzyska elementy do wykonania wraz z każdą listą zadań do wykonania.
Kontrolery i widoki MVC
Kontrolery MVC znajdują się również w folderze Kontrolery rozwiązania. HomeController
renderuje główny kod HTML dla aplikacji. Widok kontrolera głównego jest zdefiniowany w pliku Views/Home/Index.cshtml. Widok strona główna renderuje inną zawartość w zależności od tego, czy użytkownik jest zalogowany:
@if (@User.Identity.IsAuthenticated)
{
// ....
}
Gdy użytkownicy są zalogowani, widzą główny interfejs użytkownika. W przeciwnym razie widzą panel logowania. Należy pamiętać, że to renderowanie warunkowe odbywa się po stronie serwera. Nigdy nie próbuj ukrywać poufnej zawartości po stronie klienta — wszystko, co wysyłasz w odpowiedzi HTTP, jest widoczne dla osoby obserwującej nieprzetworzone komunikaty HTTP.
Client-Side JavaScript i Knockout.js
Teraz przejdźmy od strony serwera aplikacji do klienta. Szablon SPA używa kombinacji jQuery i Knockout.js do utworzenia bezproblemowego, interaktywnego interfejsu użytkownika. Knockout.js to biblioteka języka JavaScript, która ułatwia powiązanie kodu HTML z danymi. Knockout.js używa wzorca o nazwie "Model-View-ViewModel".
- Model to dane domeny (listy zadań do wykonania i elementy zadań do wykonania).
- Widok jest dokumentem HTML.
- Model widoku to obiekt JavaScript, który przechowuje dane modelu. Model widoku to abstrakcja kodu interfejsu użytkownika. Nie ma wiedzy na temat reprezentacji HTML. Zamiast tego reprezentuje abstrakcyjne funkcje widoku, takie jak "lista elementów do wykonania".
Widok jest powiązany z danymi do modelu widoku. Aktualizacje do modelu widoku są automatycznie odzwierciedlane w widoku. Powiązania działają również w innym kierunku. Zdarzenia w modelu DOM (takie jak kliknięcia) są powiązane z danymi do funkcji w modelu widoku, które wyzwalają wywołania AJAX.
Szablon SPA organizuje kod JavaScript po stronie klienta na trzy warstwy:
- todo.datacontext.js: wysyła żądania AJAX.
- todo.model.js: definiuje modele.
- todo.viewmodel.js: definiuje model widoku.
Te pliki skryptów znajdują się w folderze Scripts/app rozwiązania.
todo.datacontext obsługuje wszystkie wywołania AJAX do kontrolerów internetowego interfejsu API. (Wywołania AJAX na potrzeby logowania są definiowane gdzie indziej w ajaxlogin.js).
todo.model.js definiuje modele po stronie klienta (przeglądarki) dla list do wykonania. Istnieją dwie klasy modeli: todoItem i todoList.
Wiele właściwości w klasach modelu ma typ "ko.obserwowalny". Obserwowalne są to, jak Knockout robi swoją magię. W dokumentacji aplikacji Knockout: Można zauważyć, że "obiekt JavaScript, który może powiadamiać subskrybentów o zmianach". Gdy wartość zauważalnych zmian, Knockout aktualizuje wszystkie elementy HTML powiązane z tymi widocznymi elementami. Na przykład todoItem ma obserwowalne właściwości tytułu i isDone:
self.title = ko.observable(data.title);
self.isDone = ko.observable(data.isDone);
Możesz również subskrybować możliwe do obserwowania w kodzie. Na przykład klasa todoItem subskrybuje zmiany we właściwościach "isDone" i "title":
saveChanges = function () {
return datacontext.saveChangedTodoItem(self);
};
// Auto-save when these properties change
self.isDone.subscribe(saveChanges);
self.title.subscribe(saveChanges);
Wyświetlanie modelu
Model widoku jest zdefiniowany w todo.viewmodel.js. Model widoku jest centralnym punktem, w którym aplikacja wiąże elementy strony HTML z danymi domeny. W szablonie SPA model widoku zawiera zauważalną tablicę todoLists. Poniższy kod w modelu widoku informuje Knockout o zastosowaniu powiązań:
ko.applyBindings(window.todoApp.todoListViewModel);
Powiązanie HTML i danych
Główny kod HTML strony jest zdefiniowany w pliku Views/Home/Index.cshtml. Ponieważ używamy powiązania danych, kod HTML jest tylko szablonem do renderowania danych. Funkcja Knockout używa powiązań deklaratywnych . Elementy strony są powiązane z danymi przez dodanie atrybutu "data-bind" do elementu. Oto bardzo prosty przykład, który został pobrany z dokumentacji aplikacji Knockout:
<p>There are <span data-bind="text: myItems().count"></span> items<p>
W tym przykładzie knockout aktualizuje zawartość <elementu span> o wartości myItems.count()
. Za każdym razem, gdy ta wartość się zmieni, knockout aktualizuje dokument.
Funkcja Knockout udostępnia wiele różnych typów powiązań. Oto niektóre powiązania używane w szablonie SPA:
- foreach: umożliwia iterowanie przez pętlę i stosowanie tych samych znaczników do każdego elementu na liście. Służy do renderowania list do wykonania i elementów do wykonania. W ramach foreach powiązania są stosowane do elementów listy.
- visible: służy do przełączania widoczności. Ukryj znaczniki, gdy kolekcja jest pusta, lub wyświetl komunikat o błędzie.
- wartość: służy do wypełniania wartości formularza.
- kliknięcie: wiąże zdarzenie kliknięcia z funkcją w modelu widoku.
Ochrona przed CSRF
Fałszerzować żądania między witrynami (CSRF) jest atakiem, w którym złośliwa witryna wysyła żądanie do podatnej na zagrożenia lokacji, w której użytkownik jest obecnie zalogowany. Aby zapobiec atakom CSRF, ASP.NET MVC używa tokenów ochrony przed fałszercją, nazywanych również tokenami weryfikacji żądań. Chodzi o to, że serwer umieszcza losowo wygenerowany token na stronie internetowej. Gdy klient przesyła dane do serwera, musi zawierać tę wartość w komunikacie żądania.
Tokeny chroniące przed fałszerzami działają, ponieważ złośliwa strona nie może odczytać tokenów użytkownika z powodu zasad tego samego źródła. (Zasady tego samego źródła uniemożliwiają dostęp do zawartości dokumentów hostowanych w dwóch różnych witrynach).
ASP.NET MVC zapewnia wbudowaną obsługę tokenów ochrony przed fałszerzami za pośrednictwem klasy AntiForgery i atrybutu [ValidateAntiForgeryToken]. Obecnie ta funkcja nie jest wbudowana w internetowy interfejs API. Szablon SPA zawiera jednak niestandardową implementację internetowego interfejsu API. Ten kod jest zdefiniowany w ValidateHttpAntiForgeryTokenAttribute
klasie, która znajduje się w folderze Filtry rozwiązania. Aby dowiedzieć się więcej na temat ochrony przed atakami CSRF w internetowym interfejsie API, zobacz Zapobieganie atakom fałszerstwa żądań między witrynami (CSRF).
Podsumowanie
Szablon SPA został zaprojektowany w celu szybkiego rozpoczęcia pisania nowoczesnych, interaktywnych aplikacji internetowych. Używa biblioteki Knockout.js do oddzielenia prezentacji (znaczników HTML) od danych i logiki aplikacji. Ale Knockout nie jest jedyną biblioteką JavaScript, której można użyć do utworzenia SPA. Jeśli chcesz zapoznać się z innymi opcjami, zapoznaj się z szablonami SPA utworzonymi przez społeczność.