Одностраничное приложение. Шаблон KnockoutJS

Шаблон Knockout MVC является частью ASP.NET and Web Tools 2012.2

Скачать ASP.NET and Web Tools 2012.2

Обновление ASP.NET and Web Tools 2012.2 включает шаблон приложения Single-Page (SPA) для ASP.NET MVC 4. Этот шаблон позволяет быстро приступить к созданию интерактивных клиентских веб-приложений.

"Одностраничное приложение" (SPA) — это общий термин для веб-приложения, которое загружает одну HTML-страницу, а затем обновляет страницу динамически, а не загружает новые страницы. После начальной загрузки страницы SPA взаимодействует с сервером через запросы AJAX.

Схема, на которую показаны два поля с метками

AJAX не является новым, но сегодня существуют платформы JavaScript, которые упрощают создание и обслуживание большого сложного приложения SPA. Кроме того, HTML 5 и CSS3 упрощают создание многофункциональных пользовательских интерфейсов.

Чтобы начать работу, шаблон SPA создает пример приложения "Список действий". В этом руководстве мы рассмотрим шаблон. Сначала мы рассмотрим само приложение со списком действий, а затем рассмотрим технологические компоненты, которые заставляют его работать.

Создание нового проекта шаблона SPA

Требования:

  • Visual Studio 2012 или Visual Studio Express 2012 for Web
  • ASP.NET обновлении веб-инструментов 2012.2. Обновление можно установить здесь.

Запустите Visual Studio и выберите Создать проект на начальной странице. Или в меню Файл выберите Создать , а затем — Проект.

В области Шаблоны выберите Установленные шаблоны и разверните узел Visual C# . В разделе Visual C# выберите Интернет. В списке шаблонов проектов выберите ASP.NET веб-приложение MVC 4. Задайте для проекта имя и щелкните ОК.

Снимок экрана: диалоговое окно

В мастере создания проекта выберите Одностраничное приложение.

Снимок экрана, на котором показано диалоговое окно

Нажмите клавишу F5, чтобы создать и запустить приложение. При первом запуске приложения отображается экран входа.

Снимок экрана: экран входа в список моих действий.

Щелкните ссылку "Регистрация" и создайте нового пользователя.

Снимок экрана: экран регистрации.

После входа приложение создает список дел по умолчанию с двумя элементами. Вы можете нажать кнопку "Добавить список дел", чтобы добавить новый список.

Снимок экрана: два списка задач и кнопка

Переименуйте список, добавьте в список элементы и проверка их. Вы также можете удалить элементы или весь список. Изменения автоматически сохраняются в базе данных на сервере (фактически LocalDB на данный момент, так как приложение запускается локально).

Снимок экрана: список с тремя элементами. Последний элемент проверяется и содержит зачеркивку.

Архитектура шаблона SPA

На этой схеме показаны main стандартные блоки для приложения.

Схема, на которую показаны отдельные стандартные блоки клиента и сервера. Knockout dot j s, H T M L и J SON находятся в разделе Клиент. Точка S P NET M V C, точка S P NET Web A P I, Entity Framework и База данных находятся в разделе Server.

На стороне сервера ASP.NET MVC обслуживает HTML-код, а также обрабатывает проверку подлинности на основе форм.

веб-API ASP.NET обрабатывает все запросы, связанные с ToDoLists и ToDoItems, включая получение, создание, обновление и удаление. Клиент обменивается данными с веб-API в формате JSON.

Entity Framework (EF) — это уровень O/RM. Он является посредником между объектно-ориентированным миром ASP.NET и базовой базой данных. База данных использует LocalDB, но это можно изменить в Web.config файле. Как правило, для локальной разработки используется LocalDB, а затем выполняется развертывание в базе данных SQL на сервере с помощью миграции ef code-first.

На стороне клиента библиотека Knockout.js обрабатывает обновления страниц из запросов AJAX. Knockout использует привязку данных для синхронизации страницы с последними данными. Таким образом, вам не нужно писать код, который проходит по данным JSON и обновляет модель DOM. Вместо этого вы помещаете декларативные атрибуты в HTML, которые сообщают Knockout, как представлять данные.

Большое преимущество этой архитектуры заключается в том, что она отделяет уровень представления от логики приложения. Вы можете создать часть веб-API, ничего не зная о том, как будет выглядеть веб-страница. На стороне клиента вы создаете "модель представления" для представления данных, а модель представления использует Knockout для привязки к HTML. Это позволяет легко изменять HTML-код, не изменяя модель представления. (Мы посмотрим на Нокаут чуть позже.)

Модели

В проекте Visual Studio папка Models содержит модели, используемые на стороне сервера. (Существуют также модели на стороне клиента. Мы перейдем к этим моделям.)

Снимок экрана: открытая папка Models.

TodoItem, TodoList

Это модели базы данных для Entity Framework Code First. Обратите внимание, что эти модели имеют свойства, указывающие друг на друга. ToDoList содержит коллекцию ToDoItems, и каждый из них ToDoItem имеет ссылку на свой родительский Элемент ToDoList. Эти свойства называются свойствами навигации и представляют отношение "один ко многим" списка дел и его элементов списка дел.

Класс ToDoItem также использует атрибут [ForeignKey] , чтобы указать, что ToDoListId является внешним ключом в ToDoList таблице. Это указывает EF добавить ограничение внешнего ключа в базу данных.

[ForeignKey("TodoList")]
public int TodoListId { get; set; }
public virtual TodoList TodoList { get; set; }

TodoItemDto, TodoListDto

Эти классы определяют данные, которые будут отправляться клиенту. "DTO" означает "объект передачи данных". DTO определяет, как сущности будут сериализоваться в JSON. Как правило, существует несколько причин для использования DTO:

  • Для управления сериализируемыми свойствами. DTO может содержать подмножество свойств из модели предметной области. Это можно сделать по соображениям безопасности (для скрытия конфиденциальных данных) или просто для уменьшения объема отправляемых данных.
  • Изменение формы данных, например для выравнивания более сложной структуры данных.
  • Для сохранения любой бизнес-логики вне DTO (разделение задач).
  • Если по какой-либо причине модели предметной области не удается сериализовать. Например, циклические ссылки могут вызвать проблемы при сериализации объекта. Существуют способы решения этой проблемы в веб-API (см. раздел Обработка ссылок на циклические объекты); но использование DTO просто позволяет избежать проблемы.

В шаблоне SPA объекты DTO содержат те же данные, что и модели предметной области. Однако они по-прежнему полезны, так как они не содержат циклических ссылок из свойств навигации и демонстрируют общий шаблон DTO.

AccountModels.cs

Этот файл содержит модели членства на сайте. Класс UserProfile определяет схему для профилей пользователей в базе данных членства. (В этом случае единственными сведениями являются идентификатор пользователя и имя пользователя.) Другие классы моделей в этом файле используются для создания форм регистрации и входа пользователей.

Entity Framework

Шаблон SPA использует EF Code First. В разделе Разработка кода сначала вы определяете модели в коде, а затем EF использует модель для создания базы данных. Ef также можно использовать с существующей базой данных (Database First).

Класс TodoItemContext в папке Models является производным от DbContext. Этот класс обеспечивает "клей" между моделями и EF. Содержит TodoItemContext коллекцию ToDoItem и коллекцию TodoList . Чтобы запросить базу данных, просто напишите запрос LINQ к этим коллекциям. Например, вот как можно выбрать все списки задач для пользователя "Алиса":

TodoItemContext db = new TodoItemContext();
IEnumerable<TodoList> lists = 
    from td in db.TodoLists where td.UserId == "Alice" select td;

Вы также можете добавлять новые элементы в коллекцию, обновлять элементы или удалять элементы из коллекции, а также сохранять изменения в базе данных.

Контроллеры веб-API ASP.NET

В веб-API ASP.NET контроллеры — это объекты, обрабатывающие HTTP-запросы. Как уже упоминалось, шаблон SPA использует веб-API для включения операций CRUD с ToDoList экземплярами и ToDoItem . Контроллеры находятся в папке Контроллеры решения.

Снимок экрана: открытая папка Controllers. Для параметра Controller dot c s и To do List Controller точка c s обведена красным цветом.

  • TodoController: обрабатывает HTTP-запросы для элементов списка дел.
  • TodoListController: обрабатывает HTTP-запросы для списков задач.

Эти имена важны, так как веб-API сопоставляет путь URI с именем контроллера. (Сведения о том, как веб-API направляет HTTP-запросы к контроллерам, см. в статье Маршрутизация в веб-API ASP.NET.)

Давайте рассмотрим ToDoListController класс . Он содержит один элемент данных:

private TodoItemContext db = new TodoItemContext();

Используется TodoItemContext для взаимодействия с EF, как описано ранее. Методы на контроллере реализуют операции CRUD. Веб-API сопоставляет HTTP-запросы от клиента с методами контроллера следующим образом:

HTTP-запрос Метод контроллера Описание
GET/api/todo GetTodoLists Возвращает коллекцию списков задач.
GET /api/todo/id GetTodoList Возвращает список списка действий по идентификатору
PUT /api/todo/id PutTodoList Обновления список действий.
POST/api/todo PostTodoList Создает новый список действий.
DELETE /api/todo/id DeleteTodoList Удаляет список дел.

Обратите внимание, что URI для некоторых операций содержат заполнители для значения идентификатора. Например, чтобы удалить список с идентификатором 42, универсальный код ресурса (URI) имеет значение /api/todo/42.

Дополнительные сведения об использовании веб-API для операций CRUD см. в статье Создание веб-API, поддерживающего операции CRUD. Код для этого контроллера довольно прост. Вот несколько интересных моментов:

  • Метод GetTodoLists использует запрос LINQ для фильтрации результатов по идентификатору вошедшего пользователя. Таким образом, пользователь видит только те данные, которые ему принадлежат. Кроме того, обратите внимание, что для преобразования ToDoList экземпляров в TodoListDto экземпляры используется инструкция Select.
  • Методы PUT и POST проверка состояние модели перед изменением базы данных. Если modelState.IsValid имеет значение false, эти методы возвращают http 400, Bad Request. Дополнительные сведения о проверке модели в веб-API см. в статье Проверка модели.
  • Класс контроллера также дополнен атрибутом [Authorize] . Этот атрибут проверяет, прошел ли HTTP-запрос проверку подлинности. Если запрос не прошел проверку подлинности, клиент получает http 401, Unauthorized. Дополнительные сведения о проверке подлинности см. в статье Проверка подлинности и авторизация в веб-API ASP.NET.

Класс TodoController очень похож на TodoListController. Основное отличие заключается в том, что он не определяет методы GET, так как клиент будет получать элементы задач вместе с каждым списком дел.

Контроллеры и представления MVC

Контроллеры MVC также находятся в папке Контроллеры решения. HomeControllerотображает main HTML для приложения. Представление для контроллера Home определяется в файле Views/Home/Index.cshtml. В представлении "Главная" отображается разное содержимое в зависимости от того, выполнил ли пользователь вход:

@if (@User.Identity.IsAuthenticated)
{
    // ....
}

Когда пользователи входят в систему, они видят пользовательский интерфейс main. В противном случае они увидят панель входа. Обратите внимание, что эта условная отрисовка выполняется на стороне сервера. Никогда не пытайтесь скрыть конфиденциальное содержимое на стороне клиента— все, что вы отправляете в HTTP-ответе, будет видно тем, кто просматривает необработанные HTTP-сообщения.

Client-Side JavaScript и Knockout.js

Теперь перейдем с серверной стороны приложения к клиенту. Шаблон SPA использует сочетание jQuery и Knockout.js для создания плавного интерактивного пользовательского интерфейса. Knockout.js — это библиотека JavaScript, которая упрощает привязку HTML к данным. Knockout.js использует шаблон под названием Model-View-ViewModel.

  • Модель — это данные предметной области (списки дел и элементы ToDo).
  • Представление представляет собой HTML-документ.
  • Модель представления — это объект JavaScript, содержащий данные модели. Модель представления — это абстракция кода пользовательского интерфейса. Он не знает представления HTML. Вместо этого он представляет абстрактные признаки представления, такие как "список элементов списка дел".

Представление привязано к модели представления. Обновления в модель представления автоматически отражаются в представлении. Привязки также работают в другом направлении. События в модели DOM (например, щелчки) привязаны к функциям в модели представления, которые запускают вызовы AJAX.

Шаблон SPA упорядочивает клиентский Код JavaScript в три уровня:

  • todo.datacontext.js: отправляет запросы AJAX.
  • todo.model.js: определяет модели.
  • todo.viewmodel.js: определяет модель представления.

Схема, показывающая стрелку от knockout dot j s к представлению модели, модели и контексту данных. Стрелка между Knockout dot j s и моделью представления помечена как Привязка данных и указывает на оба элемента.

Эти файлы скриптов находятся в папке Scripts/app решения.

Снимок экрана: вложенная папка с меткой приложения открыта.

todo.datacontext обрабатывает все вызовы AJAX к контроллерам веб-API. (Вызовы AJAX для входа в систему определены в другом месте в ajaxlogin.js.)

todo.model.js определяет клиентские модели (браузер) для списков задач. Существует два класса моделей: todoItem и todoList.

Многие свойства в классах модели имеют тип ko.observable. Наблюдаемые , как Нокаут делает свою магию. Из документации по Knockout: наблюдаемый объект — это объект JavaScript, который может уведомлять подписчиков об изменениях. При изменении значения наблюдаемого объекта Knockout обновляет все элементы HTML, привязанные к этим наблюдаемым элементам. Например, todoItem имеет наблюдаемые объекты для свойств title и isDone:

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

Вы также можете подписаться на наблюдаемый объект в коде. Например, класс todoItem подписывается на изменения в свойствах isDone и title:

saveChanges = function () {
    return datacontext.saveChangedTodoItem(self);
};

// Auto-save when these properties change
self.isDone.subscribe(saveChanges);
self.title.subscribe(saveChanges);

Модель представления

Модель представления определена в todo.viewmodel.js. Модель представления — это центральная точка, в которой приложение привязывает элементы HTML-страницы к данным предметной области. В шаблоне SPA модель представления содержит наблюдаемый массив todoLists. Следующий код в модели представления указывает Knockout на применение привязок:

ko.applyBindings(window.todoApp.todoListViewModel);

HTML и привязка данных

Main HTML для страницы определяется в файле Views/Home/Index.cshtml. Так как мы используем привязку данных, HTML -это только шаблон для того, что фактически отображается. Нокаут использует декларативные привязки. Привязываете элементы страницы к данным путем добавления атрибута data-bind в элемент . Вот очень простой пример, взятый из документации по Нокауту:

<p>There are <span data-bind="text: myItems().count"></span> items<p>

В этом примере Knockout обновляет содержимое <элемента span> значением myItems.count(). Всякий раз, когда это значение меняется, Knockout обновляет документ.

Knockout предоставляет ряд различных типов привязки. Ниже приведены некоторые привязки, используемые в шаблоне SPA:

  • foreach: позволяет выполнять итерацию по циклу и применять одну и ту же разметку к каждому элементу списка. Используется для отрисовки списков дел и элементов списка дел. В foreach привязки применяются к элементам списка.
  • visible: используется для переключения видимости. Скрыть разметку, если коллекция пуста, или сделать сообщение об ошибке видимым.
  • value: используется для заполнения значений формы.
  • click: привязывает событие щелчка к функции в модели представления.

Защита от CSRF

Подделка межсайтовых запросов (CSRF) — это атака, при которой вредоносный сайт отправляет запрос на уязвимый сайт, где пользователь в данный момент выполнил вход. Чтобы предотвратить атаки CSRF, ASP.NET MVC использует маркеры защиты от подделки, также называемые маркерами проверки запросов. Идея заключается в том, что сервер помещает случайно созданный маркер на веб-страницу. Когда клиент отправляет данные на сервер, он должен включить это значение в сообщение запроса.

Защита от подделки маркеров работает, так как вредоносная страница не может прочитать маркеры пользователя из-за политик одного и того же источника. (Политики одного источника не позволяют документам, размещенным на двух разных сайтах, получать доступ к содержимому друг друга.)

ASP.NET MVC обеспечивает встроенную поддержку маркеров защиты от подделки с помощью класса AntiForgery и атрибута [ValidateAntiForgeryToken] . В настоящее время эта функция не встроена в веб-API. Однако шаблон SPA включает пользовательскую реализацию для веб-API. Этот код определяется в ValidateHttpAntiForgeryTokenAttribute классе , который находится в папке Filters решения. Дополнительные сведения о защите от CSRF в веб-API см. в статье Предотвращение атак с подделкой межсайтовых запросов (CSRF).

Заключение

Шаблон SPA предназначен для быстрого начала написания современных интерактивных веб-приложений. Она использует библиотеку Knockout.js для разделения представления (разметки HTML) от логики данных и приложения. Но Knockout — это не единственная библиотека JavaScript, используемая для создания SPA. Если вы хотите изучить другие варианты, ознакомьтесь с созданными сообществом шаблонами SPA.