Why is my function not being called on the SignalR hub - asp.net-core

I am experimenting with SignalR right now with a simple chat. I am trying to send a message to a user2 if user1 provides user2's userId from Context.ConnectionId. My Client Side code:
const sendMessage = async (user, message) => {
const chatMessage = {
user: "generic user",
message: message
};
if (connection.connectionStarted) {
try {
console.log("user: " + user);
console.log("message: " + message);
console.log("message sent");
await connection.send('SendMessage',user, chatMessage);
}
catch(e) {
console.log(e);
}
}
else {
alert('No connection to server yet.');
}
}
When I send a message from the client side, I receive the correct console.logs, making me believe that my client side code is fine. However, my Hub server is not receiving my message.
public async Task SendMessage(string user, ChatMessage message)
{
Console.WriteLine("Received user:" + user);
await Clients.Group(user).ReceiveMessage(message);
}
I never get the the user in my console. But I can't figure out why I never get the message.

If you're using Context.ConnectionId as the "user" value, then you should be using Clients.Client(user).ReceiveMessage(message); instead.
Clients.Group(...) takes a group name that you've added clients to with Groups.AddToGroupAsync(Context.ConnectionId, groupName);.

Related

How to send Message only Two user in SignalR

I want when I send message to one another two will got that message like signalR groups but I doesn't use group I do this thing without group
Please Anyone can tell how to do that
You could try
public async Task SendMessage(string user, string message)
{
await Clients.Others.SendAsync("ReceiveMessage", user, message);
}
I tried with the codes in this document,just modified the codes in hub
And the result:
Send message to specific user you could check this ducument:
Update:
I add the codes in chat.js:
document.getElementById("sendButton1").addEventListener("click", function (event) {
var user = document.getElementById("userInput").value;
var message = document.getElementById("messageInput").value;
connection.invoke("SendMessage1", user, message).catch(function (err) {
return console.error(err.toString());
});
event.preventDefault();
});
add another button in page:
<div class="col-6">
<input type="button" id="sendButton1" value="Send Message" />
</div>
Add the codes in Hub:
public async Task SendMessage1(string user, string message)
{
var a = Context.UserIdentifier;
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
Result:

Azure Signal R Service not working on Blazor Wasm app

I am trying to set up Azure Signal R Service. Currently, I can get it working if I send a message to ALL clients but if I try and use Groups it doesn't send any messages. I suspect it has to do with the Azure signal R Service. I am running this locally atm
in My Web Api Startup.cs I have the following:
services.AddSignalR()
.AddAzureSignalR(options => options.Endpoints = new[]
{
new ServiceEndpoint(Configuration.GetConnectionString("AzureSignalRConnection"))
});
and
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapHub<SignalRHub>("/SingalRHub`enter code here`");
});
Then In my Hub:
public class SignalRHub: Hub
{
public async Task Join(long deviceId)
{
await Groups.AddToGroupAsync(Context.ConnectionId, deviceId);
}
public async Task ReadTime(int deviceId)
{
await Clients.Group(deviceId).SendAsync($"ReadResponse", DateTime.Now.ToString());
}
}
On my client side: (Blazor wasm app)
private async Task InitiaizeSignalR()
{
//Intialize signal R
_hubConnection = new HubConnectionBuilder()
.WithUrl(_navigationManager.ToAbsoluteUri("/SignalRHub"))
.Build();
_hubConnection.On<string>("ReadResponse", (message) =>
{
Console.WriteLine($"Read Response: {message}");
});
//Connect to hub
await _hubConnection.StartAsync();
//Register to get messages for this DeviceId
await _hubConnection.SendAsync("Join", DeviceId);
}
Now the stange thing is that when I call this on my client, I dono get any response. However If i change it to:
await Clients.All.SendAsync($"ReadResponse", DateTime.Now.ToString());
Then my clinet will get the message?

Asp.net Core SignalR hub check if a connection is alive Than text to them

Hi I am new in SignalR asp.net core I have a hub to send the message to Specific User Id Admin & client .I want all user admin level revive message when client send the message.So i have a admin user list where client send the message .Problem is how we identify which admin is live because when i send the message to all admin if any admin not connected/live with hub then my code go to error i need to identify which user is live
How i identify in asp.net core signalR?
how i check this user is available in asp.net core signalR?
here my code block where i send the message to user
[HttpPost]
public async Task<IActionResult> Index(string userId, string message, string[] myArray)
{
foreach(var s in myArray)
{
var connections = _userConnectionManager.GetUserConnections(s);
if (connections != null && connections.Count > 0)
{
foreach (var connectionId in connections)
{
await _notificationUserHubContext.Clients.Client(connectionId).SendAsync("sendToUser", message, User.Identity.Name);//send to user
}
}
}
//get the connection from the
return View();
}
here is java script function to call the above code when click on button
$("#sendButton").click(function () {
var useridd = document.getElementById("userIdd").value;
var msg = document.getElementById("message").value;
alert(msg);
$.ajax({
type: "Post",
url: "/ComplaintSystem/ChatRoom/Index",
data: {userId : useridd, message : msg, myArray: myArray},
success: function (data) {
console.log(data);
}
});
});
In myArray revive all admin users where i send the message.

Email confirmation on ASP.NET Core and Angular 7 (ussing IdentityUser)

I want to implement email confirmation to my registration process,
I'm using Angular 7 as client, I tried to implement it myself through tutorials but most of them for MVC...
I want to know what do I need exactly and how its should work...
here is my code:
ASP core:
[HttpPost]
[Route("Register")]
public async Task<object> PostAppUser(AppUserModel model)
{
var result = await _userService.Register(model);
if (result != null)
return Ok(result);
else
return BadRequest(new { message = "Register failed! Please try again later" });
}
public async Task<object> Register(AppUserModel model)
{
if (model.SpecialCode == _appSettings.Special_Code)
model.Role = "admin";
else
model.Role = "customer";
var appUser = new AppUser()
{
UserName = model.UserName,
Email = model.Email,
FullName = model.FullName,
};
try
{
var result = await _userManager.CreateAsync(appUser, model.Password);
await _userManager.AddToRoleAsync(appUser, model.Role);
return result;
}
catch (Exception ex)
{
throw ex;
}
}
Startup:
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddScoped<IUserService, UserService>();
services.AddDbContext<AuthContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("IdentityConnection")));
services.AddDefaultIdentity<AppUser>()
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<AuthContext>();
Angular:
onSubmit(form: NgForm, userName: string) {
this.userService.login(form.value).subscribe(
(res: any) => {
localStorage.setItem('token', res.token);
this.router.navigateByUrl('/home');
this.toastr.success('Welcome ' + userName + '!' , 'Authentication granted');
},
(err: any) => {
if (err.status === 400) {
this.toastr.error('Incorrect User name of Password!', 'Authentication failed');
form.reset();
} else {
this.toastr.error('Our servers is down at the moment', 'Try again later');
form.reset();
}
}
If you want to implement the email confirmation into your application, you should:
Add instruction to Send email confirmation (with the link) into your registration method.
var token = await _userManager.GenerateEmailConfirmationTokenAsync(YourUserEntity);
It will generate a token to confirm the email of your user.
- Create a callback link for your angular application, for example:
var callBackUrl = "http://localhost:4200/Profile/ConfirmEmail?userId="+usrIdentity.Id + "&token=" + code;
And then , send the callBackUrl to the user email.
Into your angular application, you should create a route for the callBackUrl, once the user click on the link sent on the email.
You should send a request to your WebApi with the userId and the token (On The link) to confirm the user email and check if the token is valid, to do that you must implement a new post method on your controller named (ConfirmUserEmail), and bellow it, implement The following instruction:
var dbUserResult = await _userManager.FindByEmailAsync(user.IdIdentityNavigation.Email);
if (dbUserResult != null)
{
var result = await _userManager.ConfirmEmailAsync(dbUserResult, confirmUserEntity.token);
if (result.Succeeded)
{ \* Implement Your business logic here /* }
}

Unable to get error message from API Angular 6

I use the following function to Post a object of a given class.
public Post<T>(object: T, url: string, httpOptions: {}): Observable<T> {
return this.httpClient.post<T>(`${environment.apiEndpoint}` + url, object, httpOptions)
.pipe(
catchError(this.handleError)
);
}
This function is called in all the service that wants to post something. Like this.
public addEquipment(equipment: Equipment): Observable<Equipment> {
return this.shared.Post<Equipment>(equipment, this.url, this.header);
}
addEquipment is then executed within the component that uses that service. Like this.
this.equipmentService.addEquipment(result)
.subscribe((data: any) => { this.alertService.success(data) }, (error: any) => this.alertService.error(error));
The problem is when the API returns a error (that I can see includes a error message, in the network tab) it tells me that there is no body in the response. The API returns a HttpResult where the error message is added to the response field.
return new HttpResult { StatusCode = HttpStatusCode.Conflict, Response = "Error message"}
I use the following function to handle the errors.
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
}
else {
console.log(error);
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
console.log(error);
return throwError(
error.error)
};
It is Angular 6 and a ServiceStack API.
All suggestions would be appreciated.
FYI it's preferable to return structured error responses in ServiceStack which you can do with:
HttpError.Conflict("Error message");
Which will let you catch it when using ServiceStack's TypeScript ServiceClient with:
try {
var response = await client.post(request);
} catch (e) {
console.log(e.responseStatus.message);
}
But from this answer for handling errors with Angular HTTP Client it suggests the error body should be accessible with:
this.httpClient
.get("data-url")
.catch((err: HttpErrorResponse) => {
// simple logging, but you can do a lot more, see below
console.error('An error occurred:', err.error);
});