Blazor Server-Side 앱으로 만들기 쉬운 채팅 앱

18025 단어 BlazorASP.NET_Core
Blazor Server-Side 응용 프로그램에서 Blazor만으로 채팅 앱을 만듭니다.
놀랍도록 쉽게 할 수 있습니다



개발 환경



Windows10
Visual Studio 2019
.Net Core 3.0

메시지 관리 클래스 만들기


Sharedフォルダ 에, List<string>型 의 채팅 정보를 보관 유지하는 것만으로 ChatClass 를 만듭니다.

Shared/ChatClass.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BlazorApp30.Shared
{
    public class ChatClass
    {
        /// <summary>
        /// チャットメッセージを保持する
        /// </summary>
        private List<string> _messages { get; set; } = new List<string>();

        /// <summary>
        /// 任意のイベントを実行するイベントハンドラ
        /// </summary>
        public event EventHandler StateChanged;

        /// <summary>
        /// チャットメッセージを取得する
        /// </summary>
        /// <returns></returns>
        public List<string> GetMessages()
        {
            return _messages;
        }

        /// <summary>
        /// チャットメッセージを追加する
        /// </summary>
        /// <param name="str"></param>
        public void AddMessage(string str)
        {
            _messages.Add(str);

            // チャットメッセージが追加されたら、イベントを実行する
            this.StateHasChanged();
        }

        /// <summary>
        /// チャットメッセージをクリアする
        /// </summary>
        public void ClearMessages()
        {
            _messages.Clear();

            // チャットメッセージがクリアされたら、イベントを実行する
            this.StateHasChanged();
        }

        /// <summary>
        /// イベントを実行する
        /// </summary>
        private void StateHasChanged()
        {
            this.StateChanged?.Invoke(this, EventArgs.Empty);
        }
    }
}
ChatClass는 채팅 메시지를 보유하는 클래스입니다. 메시지의 취득과 추가, 클리어에는, 각각 함수를 준비해, 한층 더 EventHandler 를 준비해 주는 것으로, 사용하는 측에서 채팅 메시지가 추가된 것을 계기로, 임의의 이벤트를 실행할 수 있도록 합니다.

ChatClass를 서비스에 등록



ASP.Net Core에는 응용 프로그램을 시작할 때 모든 서비스의 인스턴스를 생성하는 메커니즘이 있습니다. 채팅 응용 프로그램은 참여하는 사용자가 메시지를 동기적으로 표시하므로 ChatClass를 싱글 톤으로 시작합니다. Blazor Server-Side이기 때문에 할 수 있는 일입니다만, 이것으로 ChatClass (은)는, 어플리케이션 전체로 유일무이의 존재가 되었습니다.

Startup.cs
        using BlazorApp30.Shared;
        
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
            services.AddServerSideBlazor();
            services.AddSingleton<WeatherForecastService>();

            // ChatClassをシングルトンで生成する
            services.AddSingleton<ChatClass>();
        }

클라이언트 화면



이번에는 Pages/Index.razor 에 입력 페이지, Pages/FetchData.razor 에 이력 페이지를 만듭니다.ChatClass 인스턴스를 복수의 화면으로 사용하는 경우, 각각의 화면에서 inject 로 선언하는 것보다, MainLayout.razorにだけ 기술해, CascadingParameter 로 인스턴스를 건네주는 것이 효율적입니다.

Shared/MainLayout.razor
@inherits LayoutComponentBase
@inject BlazorApp30.Shared.ChatClass chatClass
@implements IDisposable

<div class="sidebar">
    <NavMenu />
</div>

@*カスケードパラメータで子にインスタンスを渡す*@
<CascadingValue Value="@chatClass" Name="Chat">
    <div class="main">
        <div class="top-row px-4">
            <a href="https://docs.microsoft.com/en-us/aspnet/" target="_blank">About</a>
        </div>

        <div class="content px-4">
            @Body
        </div>
    </div>
</CascadingValue>

@code{
    protected override void OnInitialized()
    {
        // 初回時にイベントハンドラに、イベントの紐づけ
        chatClass.StateChanged += OnChatStateChanged;
    }

    void OnChatStateChanged(
        object sender, EventArgs e)
    {
        this.InvokeAsync(StateHasChanged);
    }

    void IDisposable.Dispose()
    {
        // 閉じられるとき、イベントのリリース
        chatClass.StateChanged -= OnChatStateChanged;
    }
}

조금 이미지하기 어렵지만 CascadingValue 태그로 둘러싸면 그 아래의 ページ(子)MainLayout(親) 와 같은 인스턴스를 사용할 수 있게 됩니다. 즉, 부모가 한 일은 자녀가 할 필요가 없습니다.
MainLayout 안에서는, ChatClassStateChangedイベントハンドラ 에, Component 클래스의 StateHasChangedメソッド 를 실행하도록 세트 하고 있으므로, 채팅 메세지가 추가되면 Component 클래스의 StateHasChangedメソッド 됩니다. 또, 화면 갱신시에 this.InvokeAsync (을)를 사용하는 것은, 다른 thread로부터 컨트롤을 조작하려고 화내기 때문입니다.

메시지 입력 화면


Pages/Index.razor 에 채팅 메시지 입력 화면을 만듭니다.

Pages/Index.razor
@page "/"

<input type="text" @bind-value="InputMessage" />
<button class="btn btn-primary" @onclick="_=> chat.AddMessage(InputMessage)">送信</button>

@foreach (var m in chat.GetMessages())
{
    <div style="padding: 10px; margin-bottom: 10px; border: 1px solid #333333; border-radius: 10px;">
        @m
    </div>
}

@code
{
    [CascadingParameter(Name="Chat") ] protected ChatClass chat { get; set; }

    string InputMessage = "";
}

채팅 메시지 기록 화면


Pages/FetchData.razor 에 대화 메시지의 기록 화면을 만듭니다.

Pages/FetchData.razor
@page "/fetchdata"

@using BlazorApp30.Data

<h3>チャットの履歴</h3>
<button class="btn btn-primary" @onclick="_=>chat.ClearMessages()">履歴クリア</button>

@foreach (var m in chat.GetMessages())
{
    <div style="padding: 10px; margin-bottom: 10px; border: 1px solid #333333; border-radius: 10px;">
        @m
    </div>
}

@code
{
    [CascadingParameter(Name = "Chat")] protected ChatClass chat { get; set; }
}

채팅 메시지를 사용하는 화면에서는 메시지 송수신에 관련된 코드가 없어 매우 깨끗이!
Server-Side로 화면을 렌더링하기 때문에 Server-Side이기 때문에 이루어지는 코드입니다만, 매우 재미있네요.

참고



blazorhelpwebsite.com Implementing State Management In Blazor

좋은 웹페이지 즐겨찾기