Использование SignalR с JavaScript
В этой статье я покажу базовые навыки построения приложения в реальном времени используя SignalR.
- Создаем веб-проект
- Добавить клиентскую библиотеку SignalR
- Добавить хаб SignalR
- Сконфигурируем проект, чтобы запустить SignalR в классе Startup.
- Добавим код, который отсылает сообщения клиентским приложениям.

Создаем веб-проект
- В VisualStudio выберите File > New Project
- В диалоговом окне «Create a new project» выберите «ASP.NET Core Web Application«, и нажмите Next.
- В диалоговом окне «Configure your new project«, назовите проект, например «SignalRJavaScript«, и нажмите Create.
- В диалоговом окне «Create a new ASP.NET Core web Application«, выберите .NET Core и ASP.NET Core 3.0.
- Выберите Web Application чтобы создать проект на основе рейзор страниц (Razor Pages), и далее нажмите Create.

Добавить клиентскую библиотеку SignalR
Сама инфраструктура SignalR уже влючина в APS.NET Core 3.0. Но клиентской библиотеки нет. Поэтому запустите библиотечного менеджера (LibMan) и подгрузите библиотеку unpkg.
- Перейдите на Обозреватель решений / Solution Explorer щелкните по проекту правой кнопкой и выберите Add > Client-Side Library.
- В диалоге «Add Client-Side Library» в секции провайдер / Provider выберите «unpkg»
- Чтобы подгрузить клиентскую библиотеку наберите название » @microsoft/signalr@latest«

Добавить хаб SignalR
Все классы унаследованые от класса Hub это высокоуровневая обертка над клиент-серверной комуникацией.
- Добавим в корень проекта свой класс ChatHub.cs с кодом внутри.
using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR; namespace SignalRJavaScript { public class ChatHub : Hub { public async Task SendMessage(string user, string message) { await Clients.All.SendAsync("ReceiveMessage", user, message); } } }
Сам класс Hub управляет соединениями, группами и сообщениями. Обратите внимание на метод SendMessage. Данный метод кастомный т.е. вы можете назвать его как угодно. Данный метод после компиляции появиться в JavaScript-е и из этого скрипта мы сможем вызвать его. Т.е. вызвать SendMessage на стороне клиента. В свою очередь метод SendAsync запускает событиеReceiveMessage к которому можно подписаться на стороне клиента.
Сконфигурируем проект, чтобы запустить SignalR в классе Startup.
Добавьте две строчки:
1. services.AddSignalR();
2. endpoints.MapHub<ChatHub>(«/chatHub»);
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace SignalRJavaScript { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddRazorPages(); services.AddSignalR(); <---------- 1. } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); endpoints.MapHub<ChatHub>("/chatHub"); <---------- 2. }); } } }
Добавим код, который отсылает сообщения клиентским приложениям.
В файл Pages/index.cshtml добавьте следующую разметкую
@page @model IndexModel @{ ViewData["Title"] = "Home page"; } <div class="text-center"> <h1 class="display-4">Welcome</h1> <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p> </div> <div class="container"> <div class="row"> </div> <div class="row"> <div class="col-2">User</div> <div class="col-4"><input class="form-control" type="text" id="userInput" /></div> </div> <div class="row"> <div class="col-2">Message</div> <div class="col-4"><textarea class="form-control" type="text" id="messageInput"></textarea></div> </div> <div class="row"> </div> <div class="row"> <div class="col-6"> <input class="btn btn-primary" type="button" id="sendButton" value="Send Message" /> </div> </div> </div> <div class="row"> <div class="col-12"> <hr /> </div> </div> <div class="row"> <div class="col-6"> <ul id="messagesList"></ul> </div> </div> <script src="~/lib/@@microsoft/signalr/dist/browser/signalr.js"></script> <script src="~/js/chat.js"></script>
Добавьте файл JavaScript chat.js с кодом.
"use strict"; // Получим наш объект "соединение" var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build(); // Кнопка будет неактивная, до тех пор, пока нет соединения. document.getElementById("sendButton").disabled = true; // Навешиваем событие click на элемент с id = "sendButton" // Т.е. когда мы кликаем по кнопке, то запускается наша функция обраного вызова. document.getElementById("sendButton").addEventListener("click", function (event) { // Берем тексты из контролов <input /> var user = document.getElementById("userInput").value; var message = document.getElementById("messageInput").value; // Тут черзе объект connection фактически запускаем метод "SendMessage" на сервере, // который в свою очередь с сервера оповестит всех подписчиков методом "ReceiveMessage". connection.invoke("SendMessage", user, message).catch(function (err) { return console.error(err.toString()); }); event.preventDefault(); }); // Подписываемся к событию "ReceiveMessage". // Данное событие запускается на сервере (в коде c# это метод "ReceiveMessage"), а js "слушает его" connection.on("ReceiveMessage", function (user, message) { // Как только событие отработает запуститься наша функция обратного вызова callback function var msg = message.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); var encodedMsg = user + " says " + msg; var li = document.createElement("li"); li.textContent = encodedMsg; document.getElementById("messagesList").appendChild(li); }); // Запускаем соединение асинхронно. connection.start().then(function () { // Если соединение успешное установлено, то активируем кнопку document.getElementById("sendButton").disabled = false; }).catch(function (err) { // Если соединение не удалось return console.error(err.toString()); });
- var connection = new signalR.HubConnectionBuilder().withUrl(«/chatHub»).build(); — получаем наш хаб.
- connection.invoke(«SendMessage», user, message) — отправляем сообщение
- connection.on(«ReceiveMessage», function(user, msg ){}) — слушаем событие ReceiveMessage, которое запускается на сервере.