C
C#2y ago
PontiacGTX

Signalr not sending message(s) to specific user(s)

in the hub i have setup this signature for a method
public async Task SendMessage(string sender, string receiver, string message)
{
await Clients.Users(sender, receiver).SendAsync("ReceiveMessage", receiver, message);
}
public async Task SendMessage(string sender, string receiver, string message)
{
await Clients.Users(sender, receiver).SendAsync("ReceiveMessage", receiver, message);
}
and in the client side(the page on blazor server) i have set this up for the ReceiveMessage method
public async Task OnInitializeAsync()
{

if(hub is null)
hub = new HubConnectionBuilder()
.WithUrl(_NavigationManager.ToAbsoluteUri("/ConnectionsHub"))
.Build();
hub.On<string, string>($"ReceiveMessage", // this is never triggered
async (sender, message) =>
{
var encodedMsg = $"{sender}: {message}";
ChatBox.MessageList.Add(encodedMsg);
await ChatBox.ComponentStateHasChanged();
});
hub.ServerTimeout = TimeSpan.FromMilliseconds(100000);
await hub.StartAsync();
}
public async Task OnInitializeAsync()
{

if(hub is null)
hub = new HubConnectionBuilder()
.WithUrl(_NavigationManager.ToAbsoluteUri("/ConnectionsHub"))
.Build();
hub.On<string, string>($"ReceiveMessage", // this is never triggered
async (sender, message) =>
{
var encodedMsg = $"{sender}: {message}";
ChatBox.MessageList.Add(encodedMsg);
await ChatBox.ComponentStateHasChanged();
});
hub.ServerTimeout = TimeSpan.FromMilliseconds(100000);
await hub.StartAsync();
}
and how I call this method
private async Task SendMessage(string message)
{
if(string.IsNullOrEmpty(message))
{
await PrintMessage("Error", "Cannot send an empty message");
return;
}
if (hub is not null)
{

foreach (var user in _UserList)
{
await hub.SendAsync("SendMessage", ThisUser.Email, user.User.Email,ChatBox.Message);
}

// await ChatBox.ComponentStateHasChanged();
}
}
private async Task SendMessage(string message)
{
if(string.IsNullOrEmpty(message))
{
await PrintMessage("Error", "Cannot send an empty message");
return;
}
if (hub is not null)
{

foreach (var user in _UserList)
{
await hub.SendAsync("SendMessage", ThisUser.Email, user.User.Email,ChatBox.Message);
}

// await ChatBox.ComponentStateHasChanged();
}
}
68 Replies
Yawnder
Yawnder2y ago
@PontiacGTX Right now, what is your problem? Your message isn't received by the user, or it's received by too many users?
PontiacGTX
PontiacGTX2y ago
it isnt recieved by me (who sent it) it moves into the SendAsync method in SendMessage and then it doesnt trigger the Action (I am the sender and the receiving user)
Yawnder
Yawnder2y ago
Have you debugged the service for when you connect with the client to make sure that part works, and when you try to send a message to the user, what's the value you're using for it's client?
PontiacGTX
PontiacGTX2y ago
some ranodm string but i see that the client is repeated twice maybe i shoudl use an if else
Yawnder
Yawnder2y ago
A random string? How do you expect that to work?
PontiacGTX
PontiacGTX2y ago
if it is the use myself only send it to me and not twice my username i mean the message is what i have sent (some random thing) lol
Yawnder
Yawnder2y ago
Ok, but I'm talking about the recipient. What's the value? You're actually sending the message twice, once to the recipient and once to the sender.
PontiacGTX
PontiacGTX2y ago
my username in identity i am senidn ti twice yeah but not receiving it once
Yawnder
Yawnder2y ago
Then that's probably the problem. SignalR doesn't care about your identity itself, it wants the clientId.
PontiacGTX
PontiacGTX2y ago
mmm
PontiacGTX
PontiacGTX2y ago
Stack Overflow
SignalR - Sending a message to a specific user using (IUserIdProvid...
In the latest version of Asp.Net SignalR, was added a new way of sending a message to a specific user, using the interface "IUserIdProvider". public interface IUserIdProvider { string GetUserId(
PontiacGTX
PontiacGTX2y ago
await _userManager.AddClaimAsync(user, new Claim(ClaimTypes.Email, Model.Email)); this line
Yawnder
Yawnder2y ago
Did you create and register the CustomEmailProvider? (And is the email part of the claims of the user?)
PontiacGTX
PontiacGTX2y ago
well i dont know if i setup the custom email provider where do i set it?
Yawnder
Yawnder2y ago
It's in the SO post.
PontiacGTX
PontiacGTX2y ago
i have this
builder.Services
.AddDbContext<AppDbContext>(options => { options.UseNpgsql(conString); })
.AddIdentity<AppUser, IdentityRole>(options =>
{
options.SignIn.RequireConfirmedAccount = true;
options.SignIn.RequireConfirmedEmail = true;
options.User.RequireUniqueEmail = true;
})
.AddUserStore<AppUserStore>()
.AddDefaultUI()
.AddSignInManager()
.AddEntityFrameworkStores<AppDbContext>()
.AddTokenProvider<DataProtectorTokenProvider<AppUser>>(TokenOptions.DefaultProvider);
builder.Services
.AddDbContext<AppDbContext>(options => { options.UseNpgsql(conString); })
.AddIdentity<AppUser, IdentityRole>(options =>
{
options.SignIn.RequireConfirmedAccount = true;
options.SignIn.RequireConfirmedEmail = true;
options.User.RequireUniqueEmail = true;
})
.AddUserStore<AppUserStore>()
.AddDefaultUI()
.AddSignInManager()
.AddEntityFrameworkStores<AppDbContext>()
.AddTokenProvider<DataProtectorTokenProvider<AppUser>>(TokenOptions.DefaultProvider);
then builder.Services.AddSingleton<IUserIdProvider, CustomEmailProvider>(); builder.Services.AddSignalR();
public class CustomEmailProvider : IUserIdProvider
{
public virtual string GetUserId(HubConnectionContext connection)
{
return connection.User?.FindFirst(ClaimTypes.Email)?.Value;
}
}
public class CustomEmailProvider : IUserIdProvider
{
public virtual string GetUserId(HubConnectionContext connection)
{
return connection.User?.FindFirst(ClaimTypes.Email)?.Value;
}
}
Yawnder
Yawnder2y ago
Oh, then you have the custom email provider. If you put a breakpoint in there, what happens?
PontiacGTX
PontiacGTX2y ago
PontiacGTX
PontiacGTX2y ago
just starting up (i havent sent anything)
Yawnder
Yawnder2y ago
Humn... what's the value of res?
PontiacGTX
PontiacGTX2y ago
loggged int
PontiacGTX
PontiacGTX2y ago
it skips it i think this is wrong let me try something different var res = connection.User?.Claims.FirstOrDefault(x=>x.Type==ClaimTypes.Email)?.Value; this worked somehow the other method didnt lol
Yawnder
Yawnder2y ago
Good. Then res is a Guid (well, string representation) and your message gets sent?
PontiacGTX
PontiacGTX2y ago
it si my username
public virtual string GetUserId(HubConnectionContext connection)
{

var res = connection.User?.Claims.FirstOrDefault(x=>x.Type==ClaimTypes.Email && x.Value == connection.User.Identity.Name);
return res?.Value;
}
public virtual string GetUserId(HubConnectionContext connection)
{

var res = connection.User?.Claims.FirstOrDefault(x=>x.Type==ClaimTypes.Email && x.Value == connection.User.Identity.Name);
return res?.Value;
}
so my email
Yawnder
Yawnder2y ago
That's not what you want.
PontiacGTX
PontiacGTX2y ago
why?? oh well i see the method says the Id connection User contains the id also i would like to use my email a smy idnetifier but if you say i must return the id...
Yawnder
Yawnder2y ago
Well, I might be wrong. I always used the plain SignalR UserId. Give me a sec to read on it. OH! Nevermind, it's now how I thought it was. It must return the email, you're right What it's doing is not "map the email to the userId". It's, when a connection is established, SignalR asks that provider "What do you want me to use as Id" So to recap: This must return your email in your context.
PontiacGTX
PontiacGTX2y ago
well in my context let me check
PontiacGTX
PontiacGTX2y ago
PontiacGTX
PontiacGTX2y ago
this si what the context returns no user
Yawnder
Yawnder2y ago
But you're not in the same context there.
PontiacGTX
PontiacGTX2y ago
where do you want me to check the context
Yawnder
Yawnder2y ago
In the code of the UserIdProvider, it's when you're establishing the connection as the user. There, you were sending the message. In GetUserId, the value returned is the email now, right? (if you put a breakpoint and check when you establish the connection.)
PontiacGTX
PontiacGTX2y ago
i mean it does only when I login
Yawnder
Yawnder2y ago
Of course
PontiacGTX
PontiacGTX2y ago
i have a cascade parameter on my nav and on my body fragment but wheni click to send the message it just doesnt moves onto GetUserId
Yawnder
Yawnder2y ago
Wait, you're losing me. What are you talking about now? No, it's ok. It's when the SignalR connection is established only.
PontiacGTX
PontiacGTX2y ago
I am talking about triggering the SendMessage method oh well so where do i check that the user is within the context it isnt in the hub on the server? .
MODiX
MODiX2y ago
Yawnder#7904
In GetUserId, the value returned is the email now, right?
React with ❌ to remove this embed.
PontiacGTX
PontiacGTX2y ago
it does
Yawnder
Yawnder2y ago
Great
PontiacGTX
PontiacGTX2y ago
but then it doesnt really send the mssage
Yawnder
Yawnder2y ago
Not at that moment no. Now, when you send the message, you send the same email address as recipient, correct?
PontiacGTX
PontiacGTX2y ago
yeah who is myself who sends it
Yawnder
Yawnder2y ago
And you still don't receive messages, right?
PontiacGTX
PontiacGTX2y ago
PontiacGTX
PontiacGTX2y ago
i dont recieve anything i wrote it like this and nothing triggers this
PontiacGTX
PontiacGTX2y ago
PontiacGTX
PontiacGTX2y ago
this action doesnt trigger this method
Yawnder
Yawnder2y ago
You have a breakpoint in HubOnReceiveMessage... and it doesn't get hit? Ok
PontiacGTX
PontiacGTX2y ago
it doesnt
Yawnder
Yawnder2y ago
In your hub, add this override and put a breakpoint in there: public override async Task OnDisconnectedAsync(Exception exception) Also, in SendMessage, can you check the content of Clients and see if you still have some.
PontiacGTX
PontiacGTX2y ago
ok
PontiacGTX
PontiacGTX2y ago
PontiacGTX
PontiacGTX2y ago
PontiacGTX
PontiacGTX2y ago
user seems null
Yawnder
Yawnder2y ago
If you send to Clients.All, does it work?
PontiacGTX
PontiacGTX2y ago
i will restart again and check that out yes it works so why it isnt binding the user to the email
Yawnder
Yawnder2y ago
Then I don't know. I would have to try it and play around
PontiacGTX
PontiacGTX2y ago
can i send you my repository?
Yawnder
Yawnder2y ago
I don't really have the time for that, sorry
PontiacGTX
PontiacGTX2y ago
so what can I do to make sure that it beinds the userid to the email
Yawnder
Yawnder2y ago
No idea. As I said, I always worked with the raw UserId. Maybe if you put a breakpoint in SendMessage and you check this.Users to see what's in there.
PontiacGTX
PontiacGTX2y ago
this.Clients?
Yawnder
Yawnder2y ago
There is no list of users?
PontiacGTX
PontiacGTX2y ago
Users isa method that calls certain users
PontiacGTX
PontiacGTX2y ago
PontiacGTX
PontiacGTX2y ago
there is a connection but no claims or users
Want results from more Discord servers?
Add your server
More Posts
Rider line problemI'd moved to rider but a line make me angry, anybody can help me about how can I remove this?Is it possible to publish a WPF Application into a single file with the font inside of the EXE?Is it possible to publish a WPF Application into a single file with the font inside of the EXE?Binding to Dictionary in WPF with a binding KEYhello i have a very specific problem related to WPF : i have a listbox with itemsSource <ListBox Itset default value of parameter to other parameter [Answered]ok, i am aware that this is probably not possible, but can i set default value of parameter x to vaChecking if an arbitrary (remote) URL is a file attachment, and extracting it if it is? [Answered]If I'm given an arbitrary URL (I don't have control over it), how can I check if it appears to be a How does assigning default values when creating an instance work? [Answered]I'm not sure how to ask this question. I also can't for the life of me remember what this style of iProcess.EnableRaisingEvents does not work on WindowsI have an app that have 20 workers that are other processes. On production, on ubuntu, when I close Top-level statements in MSVSSay you've created a new project with top-level statements in MSVS. Is it possible to change it to *how to format multiple conditions assignments in return statement [CLOSED] [Answered]Greetings, I was wondering, how could I properly format this piece of code. ```cs return res > PagEntity Framework One-To-One [Answered]Code at: https://paste.mod.gg/rccwzntafwoj/0 When attempting to change the database I'm getting: T