KsigDo. Knockout, SignalR, ASP.NET, MVVM, MVC и EF смешались вместе в примере многопользовательского приложения синхронизации задач в реальном времени

Грэг Дункан

Спектр технологий, использованных в этом примере, захватывает дыхание, только Ануп (автор статьи) был способен собрать их все вместе, предоставив нам пример, который мы рассмотрим…

Блокнот для неотложных дел KsigDo – Модель представления интерфейса, синхронизирующая задачи между пользователями в реальном времени с помощью ASP.NET, SignalR, Knockout MVVM и EF

Блокнот для неотложных дел KsigDo = Knockout + SignalR. Исходный код располагается на Codeplex, имейте его под рукой.

Синхронизация данных в реальном времени с точки зрения пользователей «была» сложным делом, особенно для веб-приложений. Большую часть времени второму пользователю требовалось обновлять экран, чтобы увидеть изменения, внесенные первым, или же требовалось реализовать длинную процедуру последовательного опроса, выбирающую данные и обновлять их вручную.

Теперь, с помощью SignalR и Knockout, разработчики ASP.NET могут использовать преимущества модели представления для синхронизации между пользователями, которая значительно упрощает эти сценарии при минимуме кода. В статье рассказывается, как реализовать блокнот неотложных дел (to-do notepad) в реальном времени, который будет синхронизировать данные среди пользователей, имеющих доступ к приложению. Это означает, что пользователи могут изменять свои задачи (добавлять, удалять, обновлять и т. п.), при этом остальные увидят изменения сразу же. Фокус состоит в методе, я не стараюсь создать здесь сказочный интерфейс пользователя.

Я знаю, что все мы уже устали от примеров блокнотов неотложных дел, но на этот раз давайте создадим такое приложение, которое синхронизирует задачи между вами и вашей женой (или товарищами по команде) в реальном времени с полной поддержкой операций CRUD (create, read, update и delete). И, да, мы постараемся сохранить количество кода минимальным и обслуживаемым, использую подходящую модель представлений (ох, разве это возможно на JavaScript?).

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

...

Сначала самое важное

Для начала давайте создадим новое приложение ASP.NET MVC 3.0. Чтобы создать пустой проект, я установил обновление инструментария ASP.NET MVC 3. Создав проект ASP.NET MVC, запустите консоль Nuget (View->Other Windows-> Package Manager console) и установите пакеты Nuget для Knockout и SignalR.

install-package knockoutjs

и SignalR

install-package signalr

Также установите последнюю версию Entity Framework, если у вас ее еще нет, чтобы можно было использовать возможности Code First.

Install-Package EntityFramework

Если вы уже знакомы с Knockout и SignalR, то можете пропустить следующие два параграфа и перейти прямо к разделу «Создание приложения KsigDo».

Knockout

Knockout Js – это потрясающая библиотека на JavaScript, позволяющая следовать соглашениям модели MVVM, чтобы связать пользовательские элементы управления с моделью представления JavaScript. Это здорово, потому что позволяет довольно просто создавать насыщенный интерфейс с минимальным количеством кода. Вот простой пример, демонстрирующий, как привязать HTML-элементы к модели представления JavaScript.

Вот очень простая модель представления.

...

Создание приложения KsigDo

Теперь продолжим и создадим наше приложение KsigDo. Давайте вместе двигаться шаг за шагом.

Модель задачи для последовательного использования EntityFrameworkCodeFirst

В приложении ASP.NET MVC зайдите в папку Models и добавьте новый файл модели «Code First». Наша модель крайне компактна и, как можно видеть, у нас еcть taskId и заголовок для модели, а также несколько определенных правил проверки, вроде длины заголовка. Кроме того, свойство завершенности принимает решение, завершена задача или нет.

...

TaskHubдля основных операций

Создайте в проекте ASP.NET MVC новую папку с названием «Hubs» и добавьте в нее новый файл TaskHub.cs (нет, мы пока не используем контроллеры). Да, вы можете разместить Hubs где угодно. Вот наш TaskHub, наследующий от класса SignalR.Hubs.Hub. Можно видеть, что мы используем этот Hub для выполнения большинства операций CRUD в нашей модели задачи.

...

Основное представление

Теперь давайте двинемся дальше и создадим клиентский код. Добавьте контроллер «Home» и действие «Index». Создайте новое представление «Index». Кроме того, убедитесь, что необходимые сценарии JavaScript связаны с импортируемыми библиотеками Knockout и SignalR (см. код).

Наша индексная страница получила пару моделей представления и немного HTML (представления). Для моделей представления у нас есть taskViewModel и taskListViewModel, как показано ниже. Можно заметить, что у нашего класса taskViewModel почти такие же свойства, как и у нашей модели Task, и, таким образом, SignalR может управлять сериализацией и проектированием довольно просто, даже когда мы вызываем методы в классе TaskHub.

...

Добавление и уничтожение элементов

Взгляните на addTaskMethod в модели taskListViewModel и вы увидите, что мы создали новую задачу, и затем вызвали метод «add» объекта «hub», который внутри себя вызвал метод «Add» из TaskHub на сервере. В нем можно видеть, что мы выполняем широковещательную рассылку добавляемой задачи всем клиентам, вызывая метод taskAdded на стороне клиента – и таким образом обновляем массив наблюдаемых элементов, так чтобы Knockout внутри управлял рендерингом нового элемента <li> в <ul>, основываясь на шаблоне данных «tasktemplate» (см. выше код представления, где определяется tasktemplate).

Команда уничтожить работает таким же образом, можно видеть, что кнопка «x» указывает на метод удаления для каждой конкретной taskViewModel, которая внутри вызывает метод removeTask класса taskListViewModel для вызова метода «Remove» в TaskHub с помощью прокси хаба, и оттуда на всех клиентах вызывается taskRemoved, где мы реально убираем элемент из коллекции.

Обновлениеэлемента :

Заметьте, что как только элемент привязывается к шаблону, мы подписываемся на события изменения задачи в taskViewModel. Даже когда меняется свойство, мы вызываем метод updateTask из ownerViewModel, который, в свою очередь, вызывает метод update из хаба, который посылает задачу методу update нашего TaskHub – благодаря связи с SignalR. Там мы пытаемся сохранить элемент, и если все хорошо, обновленный элемент будет разослан от TaskHub всем клиентам путем вызова метода JavaScript из taskUpdated, который мы присоединили к хабу, где на самом деле происходит обновление свойств элемента во всех клиентах.

clip_image002

Заключение

Удивительно, но это всё. Очень мало кода, очень мало усилий и замечательный результат. Спасибо ASP.NET, SignalR, Entity Framework и Knockout....