Все привыкли к push-уведомлениям в браузере. Однако создание их требует от программиста определенного опыта и желания возиться с вебсокетами и прочими фронтовыми заморочками, позволяющими веб-приложению в нужный момент отправить обновления на браузерный клиент. Более того, не всегда вебсокеты работают хорошо, поэтому приходится создавать код для поддержки нескольких транспортов — над такой штукой надо думать и хорошо её отлаживать. Очевидно, есть готовые библиотеки, которые берут это на себя. В мире веб-приложений ASP.NET это SignalR, она позволяет разработчику абстрагироваться от перечисленных сложностей и использовать простую программную модель для работы с push-уведомлениями.  SignalR дает возможность реализовать модель «publisher-subscriber» на стороне сервера. Клиенты, которыми обычно (хотя и не обязательно) являются веб-страницы, подписываются на так называемый хаб (hub), а он, в свою очередь, может отправлять им обновления. Всё как на Хабре — забегаем в хаб .NET, подписываемся, хейтим в комментариях :) Прилетающие нам обновления могут быть как отправлены в произвольное время (взгляните на страницу с комментариями: сервер отправляет браузерному клиенту только что появившийся свежий комментарий — и страница сразу же показывает комментарий пользователю), так и вызваны сообщением от клиента (кто-то даванул кнопку «обновить всё» — не браузерную, а в интерфейсе Хабра). Старый SignalR, однако, не совместим с ASP.NET Core. Поэтому, если вы хотели использовать push-уведомления в веб-приложении, раньше приходилось искать какие-то другие способы. Осенью прошедшего года увидели свет две альфа-версии SignalR Core (правильнее так: «SignalR for ASP.NET Core 2.0»), и, будем надеяться, вскоре Microsoft покажет нам бету, а затем и релиз. Чтобы честно описать всю модель программирования таких приложений, надо написать серию постов. Начнём с чего-нибудь простого: попробуем новую технологию на примере связки простенького серверного хаба и не менее простого JavaScript-клиента, которые будут передавать сообщение «НЛО прилетело и оставило это сообщение». Дело происходит на SignalR Core alpha 2 для ASP.NET Core 2. В качестве IDE используется Jetbrains Rider, потому что он клёвый! Для начала создадим пустое приложение (.NET Core/ASP.NET WebApplication): 
 В этом шаблоне проекта уже будет пакет Microsoft.AspNet.All, и всё, что нужно для запуска, там имеется. В принципе, можно сразу давить кнопку запуска приложения, и оно заработает. Необходимо установить пакет NuGet для SignalR. Обратите внимание на то, что сейчас нужно использовать галку PreRelease (которая в свою очередь добавит опцию -Pre в NuGet), поскольку мы имеем дело с пре-релизом: 
 Далее добавляем Хаб. Создаем новый класс: В SignalR Core класс, который наследуется от Hub, способен общаться c подписанными на него клиентами. Общение может проходить в нескольких вариантах: широковещательная передача «всем клиентам», «всем, кроме одного», отправка единственному клиенту или отправка определенной группе. В нашем случае мы широковещательно передадим сообщение "nlo" всем клиентам. В классе Startup нам нужно удалить дефолтный код «Hello world» и зарегистрировать наш хаб. Получится что-то подобное: В UseSignalR() мы регистрируем маршрут, по которому наш хаб будет доступен со стороны клиентов. Для отдачи статики (HTML и JavaScript) служит UseFileServer(). Нужно проверить, что оно запускается. Если нет — это проблема, нужно чинить. Для того, что веб-страница могла общаться с нашим хабом, понадобится пара скриптов. Можно было бы сделать это вручную, но пусть на нас батрачит npm. Конечно, его нужно заранее установить (он идёт в комплекте с Node.js). Консоль уже встроена в Rider, поэтому нужно её открыть, перейти в папку wwwroot и выполнить следующие команды: 
 Первый пакет — JavaScript-клиент для SignalR Core (самая свежая версия файла сегодня называется signalr-client-1.0.0-alpha2-final.js). Второй пакет — это библиотека jQuery, которая, хотя более и не требуется для SignalR Core, но, при работе с кодом для фронтенда, сильно облегчает жизнь. Можно скопировать signalr-client-1.0.0-alpha2-final.js и jquery.js в папку wwwroot, но мне лень, пусть всё остаётся именно таким, как это сгенерил npm. Далее создаем в каталоге wwwroot файл index.html. Добавляем в него ссылки на вышеприведенные скрипты, плейсхолдер для сообщений (в нашем примере его ID будет "log"), и небольшой скрипт, чтобы это все заработало вместе: Этот код на JavaScript устанавливает соединение с хабом, регистрирует callback на получение сообщения "nlo" и вызывает метод BroadcastNlo() хаба. Пробуем: 
 Отлично! Соединение установлено, и мы получаем что-то в ответ от сервера (т.е. хаба). Откроем еще пару окон браузера на тот же самый эндпоинт: 
 Здесь видно, что, по мере того, как мы открываем новые окна, сообщение "nlo" широковещательно рассылается всем подключенным клиентам. Поскольку мы не храним на сервере никакого состояния, сообщения просто добавляются к уже имеющемуся у клиентов тексту. Клиенты, подключившиеся позже (и, таким образом, пропустившие часть старых сообщений), получают и показывают нам на экране меньшее количество сообщений. Это не еще одна технология от Microsoft, подзаголовок переводится всего лишь как «Хлеба и зрелищ!» С хлебом, приняв за него вышеприведенный пример с пересылкой "nlo", мы вроде бы разобрались, теперь давайте посмотрим на что-то более красивое. В официальном репозитории с примерами для ASP.NET Core SignalR имеется неплохой готовый проект под названием «WhiteBoard». Это довольно простая и минималистическая веб-реализация доски для совещаний, где все клиенты видят в своих браузерах то, что они нарисуют на странице мышью (или пальцем, если пример гонять на тач-устройстве), совместно с другими клиентами. Можно посмотреть код и увидеть, что он написан выгодно красиво и лаконично, по сравнению с классическим дизайном веб-чата. Изображаемая картинка передаётся в виде набора отрезков (точнее, координат точек, между которыми должны рисоваться отрезки). Очевидно, информацией у нас будет не тестовая строка в том виде, как она введена пользователем, а координаты манипулятора. Далее хаб рассылает сообщения не всем клиентам (как в случае с нашим простейшим чатом), а всем, кроме передавшего информацию (отсюда — AllExcept), поскольку отправляющий клиент и так знает координаты (и, вообще говоря, уже отрисовал у себя очередной отрезочек). В свою очередь, клиенты (каждая веб-страница) отправляют данные о нарисованных их пользователями отрезках так: где draw — маршрут на зарегистрированный хаб DrawHub.  Здесь мы видим, как ASP.NET Core SignalR берет на себя довольно рутинную задачу по передаче набора данных, а не просто текстовой строки. Нам лишь остается использовать эти данные должным образом на принимающей стороне. Он неплохо скрывает под капот многие мелочи, позволяя не забивать голову совсем уж низкоуровневыми сложностями. Так что запускаем пример, вооружаемся пером (или, как я, мышью) и пробуем свои силы:  Для дальнейшего погружения в тему посмотреть доклад Dino Esposito с конференции DotNext 2016: Деврел Axiom JDK, продюсер в Failover Bar