実現したいこと
特定のユーザー向けにメッセージを送信したい
発生している問題・分からないこと
Clients.Allにて全員に送信できることはできている
受信もできているので基本的なコードは間違っていない
問題は await Clients.Users(targetIds).SendAsyncで特定のUserIDに送信したいがそこが上手くいかない
public override Task OnConnectedAsync()
{
Console.WriteLine($"SignalR接続: UserIdentifier = {Context.UserIdentifier}");
return base.OnConnectedAsync();
}
public class CustomUserIdProvider : IUserIdProvider
{
public string? GetUserId(HubConnectionContext connection)
{
var userId = connection.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
return string.IsNullOrWhiteSpace(userId) ? null : userId;
}
}
の部分でIDがNullになっている
このページを開いている段階で自身のIDが取れていない=SignalRも認識できない
とのことになるのかなと思っています
@rendermode InteractiveServerで実現はしたいが、BlazorServerだとそもそもHubは使わないなど
情報がどっちが正しいのか不明です
Blazor は初心者です 約3か月です
C#は独学ですが5年ほどしていますがAsp netなどWebシステムは初めて構築しています
基本はAzure系をベースにしています AzureApp / Azure SQL Database / Azure Storage
やりたいことはほぼ実現できるまで学習しましたが、特定ユーザー向けChatで引っかかっています
該当のソースコード
C#
1@page "/chat/{InquiryId:int}" 2 3@rendermode InteractiveServer 4 5@using Microsoft.AspNetCore.SignalR.Client 6@using System.Security.Claims 7@using Microsoft.AspNetCore.SignalR 8@using HpqWebApp.Hubs 9 10@inject IChatService ChatService 11@inject UserManager<ApplicationUser> UserManager 12@inject AuthenticationStateProvider AuthenticationStateProvider 13@inject NavigationManager NavigationManager 14@inject IHubContext<ChatHub> HubContext 15 16<PageTitle>Chat</PageTitle> 17 18<h3>問い合わせID: @InquiryId</h3> 19 20<ul> 21 @foreach (var m in Messages) 22 { 23 <li><b>@m.SentUserId:</b> @m.Text (@m.SentAt.ToShortTimeString())</li> 24 } 25</ul> 26 27<input @bind="SentName" placeholder="送信者" /> 28<input @bind="MessageText" @onkeydown="HandleKeyPress" placeholder="メッセージを入力" /> 29<button @onclick="SendMessage">送信</button> 30 31@code { 32 33 [Parameter] public int InquiryId { get; set; } 34 35 private HubConnection? hubConnection; 36 37 private string CurrentUser { get; set; } 38 private string UserRole = "A_User"; 39 private string HdwCode; 40 private string MessageText { get; set; } 41 private string SentName { get; set; } 42 43 private List<ChatMessageDetailDto> Messages = new(); 44 45 protected override async Task OnInitializedAsync() 46 { 47 var user = await AuthenticationStateProvider.GetCurrentUserAsync(UserManager); 48 if (user is null) 49 { 50 return; 51 } 52 53 //現在ユーザー取得 54 CurrentUser = user.Id; 55 56 //Hub設定 57 hubConnection = new HubConnectionBuilder() 58 .WithUrl(NavigationManager.ToAbsoluteUri("/chathub")) 59 .Build(); 60 61 //履歴取得 62 Messages = await ChatService.GetChatMessagesAsync(InquiryId); 63 64 //受信設定 65 hubConnection.On<string, string, int>("ReceiveMessage", (sentName, message, inquiryId) => 66 { 67 var msg = new ChatMessageDetailDto 68 { 69 InquiryId = inquiryId, 70 Text = message, 71 SentUserName = sentName 72 }; 73 74 Messages.Add(msg); 75 InvokeAsync(StateHasChanged); 76 }); 77 78 await hubConnection.StartAsync(); 79 80 } 81 82 /// <summary> 83 /// メッセ―ジ送信 84 /// </summary> 85 /// <returns></returns> 86 private async Task SendMessage() 87 { 88 if (string.IsNullOrWhiteSpace(MessageText)) return; 89 90 var msg = new ChatMessageDetailDto 91 { 92 InquiryId = InquiryId, 93 Text = MessageText, 94 SentUserName = SentName, 95 RoleName = UserRole, 96 SentUserId = CurrentUser 97 }; 98 99 //表示 100 Messages.Add(msg); 101 102 await ChatService.SaveMessageAsync(msg); 103 104 // SignalR で対象ユーザーに送信 105 if (hubConnection is not null) 106 { 107 await hubConnection.SendAsync("SendMessage", CurrentUser, SentName, MessageText, InquiryId); 108 } 109 110 MessageText = string.Empty; 111 112 } 113 114 private async Task HandleKeyPress(KeyboardEventArgs e) 115 { 116 if (e.Key == "Enter") 117 await SendMessage(); 118 } 119}
C#
1 public class ChatHub( 2 UserManager<ApplicationUser> userManager, 3 IChatService chatService) : Hub 4 { 5 private readonly UserManager<ApplicationUser> _userManager = userManager; 6 private readonly IChatService _chatService = chatService; 7 8 //接続時に UserIdentifier がどうなっているか確認 9 public override Task OnConnectedAsync() 10 { 11 Console.WriteLine($"SignalR接続: UserIdentifier = {Context.UserIdentifier}"); 12 return base.OnConnectedAsync(); 13 } 14 15 public async Task SendMessage(string senderId, string sentName, string messageText, int inquiryId) 16 { 17 //送信UserID 18 var sender = await _userManager.FindByIdAsync(senderId!); 19 if (sender == null) return; 20 21 //ロール取得 22 var roles = await _userManager.GetRolesAsync(sender); 23 var userRole = roles.FirstOrDefault() ?? "User"; 24 25 List<ApplicationUser> targetUsers; 26 27 if (userRole == "User") 28 { 29 // 一般ユーザー → 管理者 or SVR へ 30 var adminUsers = await _userManager.GetUsersInRoleAsync("Admin"); 31 var svrUsers = await _userManager.GetUsersInRoleAsync("SVR"); 32 33 // 例: BaseCode が一致する管理者/SVR のみに通知 34 var filteredAdmins = adminUsers.Where(u => u.BaseCode == sender.BaseCode); 35 var filteredSvrs = svrUsers.Where(u => u.BaseCode == sender.BaseCode); 36 37 targetUsers = filteredAdmins.Concat(filteredSvrs).ToList(); 38 } 39 else 40 { 41 // 管理者 or SVR → 一般ユーザー側へ 42 targetUsers = await _chatService.GetInquiryUsersAsync(inquiryId); 43 } 44 45 // 宛先の UserId リスト 46 var targetIds = targetUsers.Select(u => u.Id).Distinct().ToList(); 47 48 // 宛先ユーザーのみへ送信 49 await Clients.Users(targetIds).SendAsync("ReceiveMessage", sentName, messageText, inquiryId); 50 51 await Clients.All.SendAsync("ReceiveMessage", sentName, messageText, inquiryId); 52 } 53 }
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
ChatGPTやCopilotにも聞いたが上手くいかない
そもそもページを開く段階で
public override Task OnConnectedAsync()
public string? GetUserId(HubConnectionContext connection)
が2回呼ばれ、2回目はNullになってしまう
補足
特になし
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。