Поделиться через


Использование SignalR для ASP.NET Core с Blazor

Примечание.

Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 8 этой статьи.

Предупреждение

Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в статье о политике поддержки .NET и .NET Core. В текущем выпуске см . версию .NET 8 этой статьи.

Внимание

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

В текущем выпуске см . версию .NET 8 этой статьи.

В этом руководстве представлен базовый рабочий интерфейс для создания приложения в режиме реального времени с помощью SignalR Blazor. Эта статья полезна для разработчиков, которые уже знакомы SignalR и стремятся понять, как использовать SignalR в Blazor приложении. Подробные рекомендации по SignalR платформам Blazor см. в следующих справочных наборах документации и документации по API:

Вы узнаете, как выполнять следующие задачи:

  • Создание приложения Blazor
  • Добавление клиентской библиотеки SignalR
  • добавлять концентратор SignalR;
  • добавлять службы и конечную точку SignalR для концентратора SignalR;
  • Добавление кода компонента для чата Razor

Когда вы выполните задачи из этого руководства, у вас будет работающее приложение чата.

Необходимые компоненты

Visual Studio (последняя версия) с рабочей нагрузкой ASP.NET и веб-разработки

Пример приложения

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

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

Просмотреть или скачать образец кода (описание загрузки)

Blazor Создание веб-приложения

Следуйте указаниям по выбору инструментов:

Примечание.

Требуются visual Studio 2022 или более поздней версии и пакет SDK для .NET Core 8.0.0 или более поздней версии.

В Visual Studio:

  • Выберите "Создать проект" в окне "Пуск" или выберите "Создать>> проект" в строке меню.
  • В диалоговом окне "Создание проекта" выберите Blazor веб-приложение из списка шаблонов проектов. Нажмите кнопку Далее.
  • В диалоговом окне "Настройка нового проекта" назовите проект BlazorSignalRApp в поле "Имя проекта", включая сопоставление заглавной буквы. Использование этого точного имени проекта важно, чтобы пространства имен соответствовали коду, скопированного из учебника, в создаваемое приложение.
  • Убедитесь, что расположение приложения подходит. Оставьте решение place и проект в том же флажке каталога. Нажмите кнопку Далее.
  • В диалоговом окне "Дополнительные сведения" используйте следующие параметры:
    • Платформа. Убедитесь, что выбрана последняя платформа . Если раскрывающийся список Visual Studio Framework не включает последнюю доступную платформу .NET, обновите Visual Studio и перезапустите учебник.
    • Тип проверки подлинности: Нет
    • Настройка для HTTPS: выбрано
    • Режим интерактивной отрисовки: WebAssembly
    • Расположение интерактивности: на страницу или компонент
    • Включение примеров страниц: выбрано
    • Не используйте операторы верхнего уровня: не выбрано
    • Нажмите кнопку создания.

В этом руководстве используется компонент WebAssembly для SignalR клиента, так как он не имеет смысла использовать SignalR для подключения к концентратору из компонента интерактивного сервера в том же приложении, что может привести к исчерпанию портов сервера.

Добавление клиентской библиотеки SignalR

В обозревателе решений щелкните проект BlazorSignalRApp.Client правой кнопкой мыши и выберите пункт Управление пакетами NuGet.

Убедитесь, что в диалоговом окне Управление пакетами NuGet для параметра Источник пакета установлено значение nuget.org.

Нажав кнопку Обзор, введите Microsoft.AspNetCore.SignalR.Client в поле поиска.

В результатах поиска выберите последний выпуск Microsoft.AspNetCore.SignalR.Client пакета. Выберите Установить.

Если откроется диалоговое окно Просмотр изменений, нажмите кнопку ОК.

Если откроется диалоговое окно Принятие условий лицензионного соглашения, выберите Я принимаю, если принимаете условия.

добавлять концентратор SignalR;

В проекте сервера BlazorSignalRApp создайте папку Hubs (plural) и добавьте следующий ChatHub класс (Hubs/ChatHub.cs):

using Microsoft.AspNetCore.SignalR;

namespace BlazorSignalRApp.Hubs;

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

Добавление служб и конечной точки для концентратора SignalR

Program Откройте файл проекта сервераBlazorSignalRApp.

Добавьте пространства имен для Microsoft.AspNetCore.ResponseCompression и класс ChatHub в начало файла:

using Microsoft.AspNetCore.ResponseCompression;
using BlazorSignalRApp.Hubs;

Добавление SignalR и по промежуточному слоям сжатия ответов:

builder.Services.AddSignalR();

builder.Services.AddResponseCompression(opts =>
{
   opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
       ["application/octet-stream"]);
});

Используйте ПО промежуточного слоя для сжатия ответа в верхней части конфигурации конвейера обработки. Поместите следующую строку кода сразу после строки, которая создает приложение (var app = builder.Build();):

app.UseResponseCompression();

Добавьте конечную точку для концентратора непосредственно перед строкой, которая запускает приложение (app.Run();):

app.MapHub<ChatHub>("/chathub");

добавлять код компонента Razor для чата.

Добавьте следующий Pages/Chat.razor файл в BlazorSignalRApp.Client проект:

@page "/chat"
@rendermode InteractiveWebAssembly
@using Microsoft.AspNetCore.SignalR.Client
@inject NavigationManager Navigation
@implements IAsyncDisposable

<PageTitle>Chat</PageTitle>

<div class="form-group">
    <label>
        User:
        <input @bind="userInput" />
    </label>
</div>
<div class="form-group">
    <label>
        Message:
        <input @bind="messageInput" size="50" />
    </label>
</div>
<button @onclick="Send" disabled="@(!IsConnected)">Send</button>

<hr>

<ul id="messagesList">
    @foreach (var message in messages)
    {
        <li>@message</li>
    }
</ul>

@code {
    private HubConnection? hubConnection;
    private List<string> messages = new List<string>();
    private string? userInput;
    private string? messageInput;

    protected override async Task OnInitializedAsync()
    {
        hubConnection = new HubConnectionBuilder()
            .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
            .Build();

        hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
        {
            var encodedMsg = $"{user}: {message}";
            messages.Add(encodedMsg);
            InvokeAsync(StateHasChanged);
        });

        await hubConnection.StartAsync();
    }

    private async Task Send()
    {
        if (hubConnection is not null)
        {
            await hubConnection.SendAsync("SendMessage", userInput, messageInput);
        }
    }

    public bool IsConnected =>
        hubConnection?.State == HubConnectionState.Connected;

    public async ValueTask DisposeAsync()
    {
        if (hubConnection is not null)
        {
            await hubConnection.DisposeAsync();
        }
    }
}

Добавьте запись в компонент, чтобы получить доступ к NavMenu странице чата. Сразу Components/Layout/NavMenu.razor после <div> блока компонента Weather добавьте следующий <div> блок:

<div class="nav-item px-3">
    <NavLink class="nav-link" href="chat">
        <span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Chat
    </NavLink>
</div>

Примечание.

Отключите ПО промежуточного слоя для сжатия ответов в среде Development при использовании Горячей перегрузки. Дополнительные сведения см. в статье Руководство по ASP.NET Core BlazorSignalR.

Выполнить приложение

Следуйте указаниям по выбору инструментов:

С помощью проекта сервераBlazorSignalRApp, выбранного в Обозреватель решений, нажмите клавишу F5, чтобы запустить приложение с помощью отладки или CTRL+F5 (Windows)/'+F5 (macOS), чтобы запустить приложение без отладки.

Скопируйте URL-адрес из адресной строки, откройте другой экземпляр или вкладку браузера и вставьте URL-адрес в адресную строку.

Выберите любой браузер, введите имя и сообщение и нажмите кнопку для отправки сообщения. Имя и сообщение отображаются на обеих страницах мгновенно:

SignalRBlazor Пример приложения открыт в двух окнах браузера с обменом сообщениями.

Цитаты: Звездный путь VI. Неоткрытая страна ©1991 Paramount

Размещенный Blazor WebAssembly интерфейс

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

Следуйте указаниям по выбору инструментов для создания размещенного Blazor WebAssembly приложения:

Примечание.

Требуются Visual Studio 2022 или более поздней версии и пакет SDK для .NET Core 6.0.0 или более поздней версии.

Создание проекта

Выберите шаблон приложения Blazor WebAssembly. Выберите Далее.

Введите BlazorWebAssemblySignalRApp в поле Имя проекта. Убедитесь, что для проекта правильно указано существующее расположение или укажите новое. Выберите Далее.

В диалоговом окне Дополнительные сведения установите флажок ASP.NET Core hosted (Размещено в ASP.NET Core).

Нажмите кнопку создания.

Убедитесь, что размещенное приложение Blazor WebAssembly создано: В Обозревателе решений проверьте наличие проекта Client и проекта Server. Если проекты отсутствуют, повторите процедуру заново, убедившись, что флажок ASP.NET Core Hosted (Размещено в ASP.NET Core) установлен, прежде чем нажимать Создать.

Добавление клиентской библиотеки SignalR

В обозревателе решений щелкните проект BlazorWebAssemblySignalRApp.Client правой кнопкой мыши и выберите пункт Управление пакетами NuGet.

Убедитесь, что в диалоговом окне Управление пакетами NuGet для параметра Источник пакета установлено значение nuget.org.

Нажав кнопку Обзор, введите Microsoft.AspNetCore.SignalR.Client в поле поиска.

В результатах поиска выберите пакет Microsoft.AspNetCore.SignalR.Client. Задайте версию в соответствии с общей платформой приложения. Выберите Установить.

Если откроется диалоговое окно Просмотр изменений, нажмите кнопку ОК.

Если откроется диалоговое окно Принятие условий лицензионного соглашения, выберите Я принимаю, если принимаете условия.

добавлять концентратор SignalR;

В проекте BlazorWebAssemblySignalRApp.Server создайте папку Hubs (plural) и добавьте следующий класс ChatHub (Hubs/ChatHub.cs):

using Microsoft.AspNetCore.SignalR;

namespace BlazorWebAssemblySignalRApp.Server.Hubs;

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}
using Microsoft.AspNetCore.SignalR;

namespace BlazorWebAssemblySignalRApp.Server.Hubs;

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;

namespace BlazorWebAssemblySignalRApp.Server.Hubs
{
    public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;

namespace BlazorWebAssemblySignalRApp.Server.Hubs
{
    public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}

Добавление служб и конечной точки для концентратора SignalR

В проекте BlazorWebAssemblySignalRApp.Server откройте файл Program.cs.

Добавьте пространство имен для класса ChatHub в начало файла:

using BlazorWebAssemblySignalRApp.Server.Hubs;

Добавление SignalR и по промежуточному слоям сжатия ответов:

builder.Services.AddSignalR();
builder.Services.AddResponseCompression(opts =>
{
      opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
         new[] { "application/octet-stream" });
});

Используйте ПО промежуточного слоя сжатия ответа в верхней части конфигурации конвейера обработки сразу после строки, которая создает приложение:

app.UseResponseCompression();

Между конечными точками для контроллера и отката на стороне клиента добавьте конечную точку для концентратора. Сразу после строки app.MapControllers();добавьте следующую строку:

app.MapHub<ChatHub>("/chathub");

В проекте BlazorWebAssemblySignalRApp.Server откройте файл Startup.cs.

Добавьте пространство имен для класса ChatHub в начало файла:

using BlazorWebAssemblySignalRApp.Server.Hubs;

Добавление SignalR и по промежуточному слоям сжатия ответов:

services.AddSignalR();
services.AddResponseCompression(opts =>
{
      opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
         new[] { "application/octet-stream" });
});

Используйте ПО промежуточного слоя сжатия ответов в верхней части конфигурации конвейера обработки:

app.UseResponseCompression();

Между конечными точками для контроллеров и резервным резервом на стороне клиента добавьте конечную точку для концентратора сразу после строки endpoints.MapControllers();:

endpoints.MapHub<ChatHub>("/chathub");

добавлять код компонента Razor для чата.

В проекте BlazorWebAssemblySignalRApp.Client откройте файл Pages/Index.razor.

Замените разметку следующим кодом:

@page "/"
@using Microsoft.AspNetCore.SignalR.Client
@inject NavigationManager Navigation
@implements IAsyncDisposable

<PageTitle>Index</PageTitle>

<div class="form-group">
    <label>
        User:
        <input @bind="userInput" />
    </label>
</div>
<div class="form-group">
    <label>
        Message:
        <input @bind="messageInput" size="50" />
    </label>
</div>
<button @onclick="Send" disabled="@(!IsConnected)">Send</button>

<hr>

<ul id="messagesList">
    @foreach (var message in messages)
    {
        <li>@message</li>
    }
</ul>

@code {
    private HubConnection? hubConnection;
    private List<string> messages = new List<string>();
    private string? userInput;
    private string? messageInput;

    protected override async Task OnInitializedAsync()
    {
        hubConnection = new HubConnectionBuilder()
            .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
            .Build();

        hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
        {
            var encodedMsg = $"{user}: {message}";
            messages.Add(encodedMsg);
            StateHasChanged();
        });

        await hubConnection.StartAsync();
    }

    private async Task Send()
    {
        if (hubConnection is not null)
            {
                await hubConnection.SendAsync("SendMessage", userInput, messageInput);
            }
    }

    public bool IsConnected =>
        hubConnection?.State == HubConnectionState.Connected;

    public async ValueTask DisposeAsync()
    {
        if (hubConnection is not null)
        {
            await hubConnection.DisposeAsync();
        }
    }
}
@page "/"
@using Microsoft.AspNetCore.SignalR.Client
@inject NavigationManager Navigation
@implements IAsyncDisposable

<PageTitle>Index</PageTitle>

<div class="form-group">
    <label>
        User:
        <input @bind="userInput" />
    </label>
</div>
<div class="form-group">
    <label>
        Message:
        <input @bind="messageInput" size="50" />
    </label>
</div>
<button @onclick="Send" disabled="@(!IsConnected)">Send</button>

<hr>

<ul id="messagesList">
    @foreach (var message in messages)
    {
        <li>@message</li>
    }
</ul>

@code {
    private HubConnection? hubConnection;
    private List<string> messages = new List<string>();
    private string? userInput;
    private string? messageInput;

    protected override async Task OnInitializedAsync()
    {
        hubConnection = new HubConnectionBuilder()
            .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
            .Build();

        hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
        {
            var encodedMsg = $"{user}: {message}";
            messages.Add(encodedMsg);
            StateHasChanged();
        });

        await hubConnection.StartAsync();
    }

    private async Task Send()
    {
        if (hubConnection is not null)
            {
                await hubConnection.SendAsync("SendMessage", userInput, messageInput);
            }
    }

    public bool IsConnected =>
        hubConnection?.State == HubConnectionState.Connected;

    public async ValueTask DisposeAsync()
    {
        if (hubConnection is not null)
        {
            await hubConnection.DisposeAsync();
        }
    }
}
@page "/"
@using Microsoft.AspNetCore.SignalR.Client
@inject NavigationManager NavigationManager
@implements IAsyncDisposable

<div class="form-group">
    <label>
        User:
        <input @bind="userInput" />
    </label>
</div>
<div class="form-group">
    <label>
        Message:
        <input @bind="messageInput" size="50" />
    </label>
</div>
<button @onclick="Send" disabled="@(!IsConnected)">Send</button>

<hr>

<ul id="messagesList">
    @foreach (var message in messages)
    {
        <li>@message</li>
    }
</ul>

@code {
    private HubConnection hubConnection;
    private List<string> messages = new List<string>();
    private string userInput;
    private string messageInput;

    protected override async Task OnInitializedAsync()
    {
        hubConnection = new HubConnectionBuilder()
            .WithUrl(NavigationManager.ToAbsoluteUri("/chathub"))
            .Build();

        hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
        {
            var encodedMsg = $"{user}: {message}";
            messages.Add(encodedMsg);
            StateHasChanged();
        });

        await hubConnection.StartAsync();
    }

    async Task Send() =>
        await hubConnection.SendAsync("SendMessage", userInput, messageInput);

    public bool IsConnected =>
        hubConnection.State == HubConnectionState.Connected;

    public async ValueTask DisposeAsync()
    {
        if (hubConnection is not null)
        {
            await hubConnection.DisposeAsync();
        }
    }
}
@page "/"
@using Microsoft.AspNetCore.SignalR.Client
@inject NavigationManager NavigationManager
@implements IDisposable

<div class="form-group">
    <label>
        User:
        <input @bind="userInput" />
    </label>
</div>
<div class="form-group">
    <label>
        Message:
        <input @bind="messageInput" size="50" />
    </label>
</div>
<button @onclick="Send" disabled="@(!IsConnected)">Send</button>

<hr>

<ul id="messagesList">
    @foreach (var message in messages)
    {
        <li>@message</li>
    }
</ul>

@code {
    private HubConnection hubConnection;
    private List<string> messages = new List<string>();
    private string userInput;
    private string messageInput;

    protected override async Task OnInitializedAsync()
    {
        hubConnection = new HubConnectionBuilder()
            .WithUrl(NavigationManager.ToAbsoluteUri("/chathub"))
            .Build();

        hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
        {
            var encodedMsg = $"{user}: {message}";
            messages.Add(encodedMsg);
            StateHasChanged();
        });

        await hubConnection.StartAsync();
    }

    async Task Send() =>
        await hubConnection.SendAsync("SendMessage", userInput, messageInput);

    public bool IsConnected =>
        hubConnection.State == HubConnectionState.Connected;

    public void Dispose()
    {
        _ = hubConnection?.DisposeAsync();
    }
}

Примечание.

Отключите ПО промежуточного слоя для сжатия ответов в среде Development при использовании Горячей перегрузки. Дополнительные сведения см. в статье Руководство по ASP.NET Core BlazorSignalR.

Выполнить приложение

Следуйте указаниям по выбору инструментов:

В обозревателе решений выберите проект BlazorWebAssemblySignalRApp.Server. Нажмите клавишу F5, чтобы запустить приложение с отладкой, или CTRL+F5 (Windows) либо +F5 (macOS), чтобы запустить его без отладки.

Внимание

При выполнении размещенного Blazor WebAssembly приложения запустите приложение из проекта решенияServer.

Для сеанса отладки должен требуется выбрать браузер Google Chrome или Microsoft Edge.

Если приложение не удается запустить в браузере:

  • В консоли .NET убедитесь, что решение выполняется из проекта "Server".
  • Обновите браузер с помощью кнопки перезагрузки браузера.

Скопируйте URL-адрес из адресной строки, откройте другой экземпляр или вкладку браузера и вставьте URL-адрес в адресную строку.

Выберите любой браузер, введите имя и сообщение и нажмите кнопку для отправки сообщения. Имя и сообщение отображаются на обеих страницах мгновенно:

SignalRBlazor Пример приложения открыт в двух окнах браузера с обменом сообщениями.

Цитаты: Звездный путь VI. Неоткрытая страна ©1991 Paramount

Следующие шаги

Из этого руководства вы узнали, как:

  • Создание приложения Blazor
  • Добавление клиентской библиотеки SignalR
  • добавлять концентратор SignalR;
  • добавлять службы и конечную точку SignalR для концентратора SignalR;
  • Добавление кода компонента для чата Razor

Подробные рекомендации по SignalR платформам Blazor см. в следующих справочных наборах документации:

Дополнительные ресурсы