ASP.NET Core で WebSocket を使おうと思ったら SignalR Core というものがあるのを知ったので、試してみました。
尚、WebSocket は昔に Node.js と Socket.IO を使ってみたことがあるのですが、SignalR は初めて触ります。
環境
- Visual Studio 2017
- ASP.NET Core 2.0
ASP.NET Core 2.0 の MVC テンプレートプロジェクトをベースとします。
サーバーサイドの実装
SignalR Core のインストール
NuGet パッケージマネージャーコンソールで以下のコマンドでインストールします。
(現在は alpha 版なので、-pre
をつけてインストールする必要があります。)
PM> Install-Package Microsoft.AspNetCore.SignalR -pre
Hub クラスの作成
SignalR ではPersistent Connection と Hub という2つの通信モデルがあるようです。
今回は Hub を使用します。
SignalR.Hub
を継承したクラスを作成します。
using Microsoft.AspNetCore.SignalR;
// 中略
public class SignalRTest : Hub
{
public Task Send(string data)
{
return Clients.All.InvokeAsync("AddMessage", data);
}
}
これで API が RPC として実装され、外部から Send
メソッドが使用可能となります。
Startup.cs の変更
SignalR を使用するための準備として、Startup
クラスの ConfigureServices
メソッドに AddSignalR
を追加します。
public void ConfigureServices(IServiceCollection services)
{
services.AddSignalR();// <-- SignalR
services.AddMvc();
}
また、Startup
クラスの Configure
メソッドに UseSignalR
を以下のように追加します。
app.UseSignalR(routes => // <-- SignalR
{
routes.MapHub<SignalRTest>(nameof(SignalRTest));
});
ここまで実装した状態でプログラムを実行し、http://localhost:xxxxx/SignalR
を開いたときに Connection ID required
と表示されれば正常です。
クライアントサイドの実装
SignalR の JavaScript Client を使用します。
SignalR Client のインストール
ASP.NET Core では SignalR の JavaScript 用クライアントも新しくなっているようです。
ASP.NET Core ではフロントエンドのパッケージ管理は Bower で管理されていましたが、現在では Bower は非推奨となっているので、この新しい SignalR Client も Bower では提供されていないようです。
なので、上記のサイトに書いてある通り、npm でインストールします。
npm install @aspnet/signalr-client
インストールが完了したら、signalr-client.js
をプロジェクト配下の wwwroot/js
にコピーします。
尚、現在ではまだ alpha 版なので、ファイル名は signalr-client-1.0.0-alpha2-final.js
のようになっています。
View の追加
ASP.NET Core の MVC テンプレートプロジェクトに対して、Views/Home/SignalR.cshtml
というファイルを作成しました。
Script の読み込み
従来の SignalR では、Script ファイルに加えて、SignalR が動的に生成する ~/signalR/hubs
というフォルダも読み込む必要があったようですが、SignalR Core では不要になったようです。
なので、以下の一行で OK です。
<script src="~/js/signalr-client-1.0.0-alpha2-final.min.js"></script>
ASP.NET Core の MVC テンプレートプロジェクトでは、_Layout.cshtml
に以下のセクションが定義されています。
@RenderSection("Scripts", required: false)
従って、SignalR を使用したい View で、Script セクションを作成し、そこで SignalR の Script を読み込ませたいと思います。
セクションについては以下を参照してください。
SignalR.cshtml
に以下を記述します。
@section scripts {
<environment include="Development">
<script src="~/js/signalr-client-1.0.0-alpha2-final.min.js"></script>
</environment>
}
SignalR の使用
まずは簡単なサンプルとして、上記のコードに以下のようなコードを追加しました。
@section scripts {
<environment include="Development">
<script src="~/js/signalr-client-1.0.0-alpha2-final.min.js"></script>
</environment>
<script>
$(function () {
let connection = new signalR.HubConnection('/SignalRTest');
connection.start()
.then(() => {
console.log('connected');
connection.invoke('send', 'Hello');
});
connection.on('AddMessage', data => {
console.log('recieved: ' + data);
});
});
</script>
}
signalR.HubConnection
で Hub
クラスを継承したクラスを指定します。
connection.invoke('send', 'Hello');
で、Hub クラス内の Send
メソッドをコールしています。
connection.on('AddMessage',...);
で、AddMessage
というメッセージを受信したときの処理を定義しています。
Controller の変更
HomeController.cs
に以下の View に対応したアクションメソッドを追加しました。
public IActionResult SignalR()
{
return View();
}
とりあえず実行
以上まで実装し、デバッガを起動し、/Home/SignalR
にアクセスします。
デバッガのコンソールログには以下のように出力されます。
メッセージの送信ボタンを実装
SignalRTest.cshtml
を以下のように変更してみます。
@{
ViewData["Title"] = "SignalR Test";
}
@section scripts {
<environment include="Development">
<script src="~/js/signalr-client-1.0.0-alpha2-final.min.js"></script>
</environment>
<script>
$(function () {
let connection = new signalR.HubConnection('/SignalRTest');
connection.start()
.then(() => {
console.log('connected');
connection.invoke('send', 'Hello');
});
connection.on('AddMessage', data => {
console.log(data);
$('#messages').append($('<li>').text(data));
});
$("#sendButton").click(function () {
connection.invoke('send', $('#sendMessage').val());
});
});
</script>
}
<h2>SignalR Test</h2>
<input type="text" id="sendMessage" placeholder="Enter report name" />
<input type="button" id="sendButton" value="Send" />
<ul id="messages"></ul>
実行結果は以下のようになります。
感想
SignalR Core はまだ正式リリース前であり、また ASP.NET Core 自体の情報が少ないこともあり、ここまで動くようにするだけでも結構苦労しました。
しかし、実際動いたコードだけをみると、とても簡単に双方向通信が実現できて便利だなと思いました。
参考 URL
SignalR
- https://docs.microsoft.com/en-us/aspnet/core/fundamentals/websockets
- http://blog.livedoor.jp/monthly_check/archives/70912403.html
- http://matsujirushi.hatenablog.jp/entry/2017/09/29/232258
- https://blogs.msdn.microsoft.com/webdev/2017/09/14/announcing-signalr-for-asp-net-core-2-0/
WebSocket