LoginSignup
2
1

More than 3 years have passed since last update.

ASP.NET Core SignalRを使用してサーバからメッセージをプッシュする

Posted at

目的

・Webアプリケーションとしてローカルネットワーク内で使用する
・WebSocket等を使用してサーバからメッセージをプッシュする
・.NET Coreを使用する

SignalR の概要(公式ドキュメントからの引用)

https://docs.microsoft.com/ja-jp/aspnet/core/signalr/introduction?view=aspnetcore-3.1
ASP.NET Core SignalR は、リアルタイムの web 機能をアプリに簡単に追加できるオープンソースライブラリです。 リアルタイム web 機能を使用すると、サーバー側のコードでクライアントにコンテンツを瞬時にプッシュできます。

SignalR は、リアルタイム通信を処理するための次の手法をサポートしています (正常なフォールバックの順序)。
WebSocket

チュートリアル

公式ドキュメントのチュートリアルとしてチャットアプリを作成する。
機能としては、クライアントからメッセージを送信、サーバはメッセージを受け取ると、全クライアントに対してそのメッセージを送信する。
省かれている工程もなく、Visual Studio、Visual Studio Code、Visual Studio for Macそれぞれの手順が記載されており、公式ドキュメント通りに実装すれば問題なくできた。
以下で手順を追いながらコメントを記載。

必須コンポーネント

  • Visual Studio Code
  • C# for Visual Studio Code (最新バージョン)
  • .NET Core 3.0 SDK 以降

※C# for Visual Studio CodeはVisual Studio Codeの拡張機能

Web アプリ プロジェクトを作成する

ターミナルで以下コマンドを実行

dotnet new webapp -o SignalRChat
code -r SignalRChat

SignalRChatフォルダにwebアプリケーションのプロジェクトを作成
SignalRChatフォルダをVisual Studio Codeで開く

※newコマンドで作成できるプロジェクトの種類については以下参照
https://docs.microsoft.com/ja-jp/dotnet/core/tools/dotnet-new

SignalR クライアント ライブラリを追加する

SignalRChatフォルダ内で以下コマンドを実行

dotnet tool install -g Microsoft.Web.LibraryManager.Cli
libman install @microsoft/signalr@latest -p unpkg -d wwwroot/js/signalr --files dist/browser/signalr.js --files dist/browser/signalr.min.js

SignalR ハブを作成する

SignalRChat以下にHubsフォルダを作成、Hubsフォルダ内にChatHub.csを作成する
サーバ側の処理を実装する

// ChatHub.cs

using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

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

SendMessageというメッセージをクライアントから受信した場合に、すべてのクライアントに対して"ReceiveMessage"というメッセージをパラメータ(user, message)をつけて送信する
メッセージ受信処理は非同期処理としてタスクにしている

SignalR を構成する

Startup.csに以下の"// +++ 追加 +++"部分を追加する

// Startup.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using SignalRChat.Hubs; // +++ 追加 +++

namespace SignalRChat
{
    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(); // +++ 追加 +++
        }

        // 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"); // +++ 追加 +++
            });
        }
    }
}

SignalR クライアント コードを追加する

クライアント側の画面を実装する

userを入力するテキスト、messageを入れるテキスト、送信するためのボタン、受信したメッセージを表示するリストを配置する
Pages\Index.cshtmlを以下の内容に書き換える

@page
    <div class="container">
        <div class="row">&nbsp;</div>
        <div class="row">
            <div class="col-2">User</div>
            <div class="col-4"><input type="text" id="userInput" /></div>
        </div>
        <div class="row">
            <div class="col-2">Message</div>
            <div class="col-4"><input type="text" id="messageInput" /></div>
        </div>
        <div class="row">&nbsp;</div>
        <div class="row">
            <div class="col-6">
                <input 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="~/js/signalr/dist/browser/signalr.js"></script>
<script src="~/js/chat.js"></script>

クライアント側の処理を実装する

wwwroot/js フォルダー内にchat.js 作成する

// chat.js

"use strict";

// コネクション作成(URLはStartup.csで追加済)
var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();

//Disable send button until connection is established
document.getElementById("sendButton").disabled = true;

// "ReceiveMessage"受信時にメッセージをリストに追加
connection.on("ReceiveMessage", function (user, message) {
    var msg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
    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());
});

// 送信ボタンクリック時に"SendMessage"を入力されたパラメータ(user, message)をつけて送信
document.getElementById("sendButton").addEventListener("click", function (event) {
    var user = document.getElementById("userInput").value;
    var message = document.getElementById("messageInput").value;
    connection.invoke("SendMessage", user, message).catch(function (err) {
        return console.error(err.toString());
    });
    event.preventDefault();
});

アプリを実行する

以下コマンドを実行する

dotnet watch run -p SignalRChat.csproj

watchをつけることで、コード変更をリアルタイムに画面に反映する
アプリケーションを配布する場合はdotnet publishする

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1