Asp.Net SignalRの最新バージョンでは、インターフェイス「IUserIdProvider」を使用して、特定のユーザーにメッセージを送信する新しい方法が追加されました。
public interface IUserIdProvider
{
string GetUserId(IRequest request);
}
public class MyHub : Hub
{
public void Send(string userId, string message)
{
Clients.User(userId).send(message);
}
}
私の質問は次のとおりです。自分のメッセージの送信先を知るにはどうすればよいですかこの新しい方法の説明は非常に表面的です。また、このバグを含むSignalR 2.0.0のドラフトステートメントはコンパイルされません。誰かがこの機能を実装していますか?
詳細: http://www.asp.net/signalr/overview/signalr-20/hubs-api/mapping-users-to-connections#IUserIdProvider
抱擁。
SignalRは、各接続にConnectionIdを提供します。どの接続が誰(ユーザー)に属するかを見つけるには、接続とユーザーの間にマッピングを作成する必要があります。これは、アプリケーションでユーザーを識別する方法によって異なります。
SignalR 2.0では、ASP.NET認証中に設定されたログインユーザー識別子である組み込みIPrincipal.Identity.Name
を使用してこれを行います。
ただし、Identity.Nameを使用する代わりに別の識別子を使用して、ユーザーとの接続をマップする必要がある場合があります。この目的のために、この新しいプロバイダーをカスタム実装で使用して、ユーザーを接続にマッピングできます。
アプリケーションがuserId
を使用して各ユーザーを識別すると仮定します。次に、特定のユーザーにメッセージを送信する必要があります。 userId
とmessage
がありますが、SignalRはuserIdと接続の間のマッピングも知っている必要があります。
これを実現するには、最初にIUserIdProvider
を実装する新しいクラスを作成する必要があります。
public class CustomUserIdProvider : IUserIdProvider
{
public string GetUserId(IRequest request)
{
// your logic to fetch a user identifier goes here.
// for example:
var userId = MyCustomUserClass.FindUserId(request.User.Identity.Name);
return userId.ToString();
}
}
2番目のステップは、SignalRにデフォルトの実装の代わりにCustomUserIdProvider
を使用するように指示することです。これは、ハブ構成の初期化中にStartup.csで実行できます。
public class Startup
{
public void Configuration(IAppBuilder app)
{
var idProvider = new CustomUserIdProvider();
GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => idProvider);
// Any connection or hub wire up and configuration should go here
app.MapSignalR();
}
}
これで、ドキュメントに記載されているuserId
を使用して、特定のユーザーにメッセージを送信できます。
public class MyHub : Hub
{
public void Send(string userId, string message)
{
Clients.User(userId).send(message);
}
}
お役に立てれば。
ここからが始まりです。提案/改善にオープンです。
サーバ
public class ChatHub : Hub
{
public void SendChatMessage(string who, string message)
{
string name = Context.User.Identity.Name;
Clients.Group(name).addChatMessage(name, message);
Clients.Group("[email protected]").addChatMessage(name, message);
}
public override Task OnConnected()
{
string name = Context.User.Identity.Name;
Groups.Add(Context.ConnectionId, name);
return base.OnConnected();
}
}
JavaScript
(addChatMessage
およびsendChatMessage
も上記のサーバーコードのメソッドであることに注意してください)
$(function () {
// Declare a proxy to reference the hub.
var chat = $.connection.chatHub;
// Create a function that the hub can call to broadcast messages.
chat.client.addChatMessage = function (who, message) {
// Html encode display name and message.
var encodedName = $('<div />').text(who).html();
var encodedMsg = $('<div />').text(message).html();
// Add the message to the page.
$('#chat').append('<li><strong>' + encodedName
+ '</strong>: ' + encodedMsg + '</li>');
};
// Start the connection.
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
// Call the Send method on the hub.
chat.server.sendChatMessage($('#displayname').val(), $('#message').val());
// Clear text box and reset focus for next comment.
$('#message').val('').focus();
});
});
});
テスト中
これは、特定のユーザーをターゲットにするために(プロバイダーを使用せずに)SignarRを使用する方法です。
private static ConcurrentDictionary<string, string> clients = new ConcurrentDictionary<string, string>();
public string Login(string username)
{
clients.TryAdd(Context.ConnectionId, username);
return username;
}
// The variable 'contextIdClient' is equal to Context.ConnectionId of the user,
// once logged in. You have to store that 'id' inside a dictionaty for example.
Clients.Client(contextIdClient).send("Hello!");
機能については SignalR Tests をご覧ください。
テスト「SendToUser」は、通常のowin認証ライブラリを使用して渡されたユーザーIDを自動的に取得します。
シナリオは、複数のデバイス/ブラウザから接続したユーザーがいて、アクティブなすべての接続にメッセージをプッシュしたい場合です。