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

по Майк Уоссон

Шаблон "маскирование MVC" является частью ASP.NET and Web Tools 2012,2

Загрузка ASP.NET and Web Tools 2012,2

Обновление ASP.NET and Web Tools 2012,2 содержит шаблон одностраничного приложения (SPA) для ASP.NET MVC 4. Этот шаблон предназначен для быстрого создания интерактивных веб-приложений на стороне клиента.

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

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

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

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

Требования

  • Visual Studio 2012 или Visual Studio Express 2012 для Web
  • Обновление ASP.NET Web Tools 2012,2. Это обновление можно установить здесь.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Модели

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

TodoItem, TodoList

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

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

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

Тодоитемдто, Тодолистдто

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

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

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

AccountModels.cs

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

Entity Framework

Шаблон SPA использует EF Code First. В 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 решения.

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

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

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

private TodoItemContext db = new TodoItemContext();

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

HTTP-запрос Метод контроллера Description
GET/api/todo GetTodoLists Возвращает коллекцию списков задач.
ПОЛУЧИТЬидентификатор /АПИ/Тодо/ GetTodoList Получает список задач по ИДЕНТИФИКАТОРу.
Размещениеидентификатора /АПИ/Тодо/ PutTodoList Обновляет список задач.
POST/api/todo PostTodoList Создает новый список задач.
УДАЛИТЬидентификатор /АПИ/Тодо/ DeleteTodoList Удаляет список TODO.

Обратите внимание, что идентификаторы URI для некоторых операций содержат заполнители для значения идентификатора. Например, чтобы удалить список в с ИДЕНТИФИКАТОРом 42, URI /api/todo/42.

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

  • Метод GetTodoLists использует запрос LINQ для фильтрации результатов по ИДЕНТИФИКАТОРу вошедшего в систему пользователя. Таким образом, пользователь видит только данные, принадлежащие ему. Кроме того, обратите внимание, что инструкция SELECT используется для преобразования экземпляров ToDoList в экземпляры TodoListDto.
  • Методы размещения и POST перед изменением базы данных проверяют состояние модели. Если ModelState. IsValid имеет значение false, эти методы возвращают HTTP 400, недопустимый запрос. Дополнительные сведения см. в статье Проверка модели в веб-API при проверке модели.
  • Класс Controller также снабжен атрибутом [авторизовать] . Этот атрибут проверяет, прошел ли HTTP-запрос проверку подлинности. Если запрос не прошел проверку подлинности, клиент получает HTTP 401 и не авторизован. Дополнительные сведения см. в статье Проверка подлинности при проверке подлинности и авторизация веб-API ASP.NET.

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

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

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

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

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

Клиентский сценарий JavaScript и выколачивание. js

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

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

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

Шаблон SPA организует клиентский сценарий JavaScript на три уровня:

  • TODO. DataContext. js: отправляет запросы AJAX.
  • TODO. Model. js: определяет модели.
  • TODO. ViewModel. js: определяет модель представления.

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

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

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

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

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

Вы также можете подписываться на наблюдаемый код. Например, класс todoItem подписывается на изменения в свойствах «Done» и «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 модель представления содержит наблюдаемый массив Тодолистс. Следующий код в модели представления указывает маскирование для применения привязок:

ko.applyBindings(window.todoApp.todoListViewModel);

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

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

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

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

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

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

Защита от защиты от CSRF

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

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

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

Заключение

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