Prerequisites
- What is your product version? v11.3.0
- What is your product type (Angular or MVC)? MVC
- What is product framework type (.net framework or .net core)? .net core
Hi,
I use notificationPublisher to send a notification to all users using the below code and it works for the web application.
await _notificationPublisher.PublishAsync(AppNotificationNames.NewIncident, notificationData,severity: NotificationSeverity.Warn);
But when I connect, using signalr, to abpcommonhub in xamarin application (connection established successfully based on
https://support.aspnetzero.com/QA/Questions/6841/Push-notification-implementation-in-Xamarin-Mobile-application) and subscribe to above notification message, I cannot receive it with the below hubconnection message subscription code.
HubConnection.On(AppNotificationNames.NewIncident, (message) => { Console.WriteLine("TEST"); });
Below is the code of NotificationService in Xamarin application.
public class NotificationService : ISingletonDependency, INotificationService { public HubConnection HubConnection { get; }
private readonly IAccessTokenManager _accessTokenManager;
private bool _isConnecting;
public NotificationService(IAccessTokenManager accessTokenManager)
{
try
{
_accessTokenManager = accessTokenManager;
HubConnection = new HubConnectionBuilder()
.WithUrl(CreateHubUrl(),
(opts) =>
{
opts.HttpMessageHandlerFactory = (message) =>
{
if (message is HttpClientHandler clientHandler)
// bypass SSL certificate
clientHandler.ServerCertificateCustomValidationCallback +=
(sender, certificate, chain, sslPolicyErrors) => { return true; };
return message;
};
}
)
.ConfigureLogging(logging => {
logging.SetMinimumLevel(LogLevel.Debug);
logging.AddConsole();
logging.AddDebug();
})
.Build();
HubConnection.On<string>(AppNotificationNames.NewIncident, (message) =>
{
Console.WriteLine("TEST");
});
HubConnection.Closed += TryToConnectIfNeeds;
ConnectAsync().ConfigureAwait(true);
}
catch (Exception ex)
{
ExceptionHandler.LogException(ex);
}
}
private async Task TryToConnectIfNeeds(Exception connectionException)
{
try
{
ExceptionHandler.LogException(connectionException);
if (!_accessTokenManager.IsUserLoggedIn)
{
return;
}
await Task.Delay(new Random().Next(0, 5) * 1000);
await HubConnection.StartAsync();
}
catch (Exception ex)
{
ExceptionHandler.LogException(ex);
}
}
public async Task<bool> ConnectAsync()
{
try
{
if (HubConnection.State == HubConnectionState.Connected)
{
return true;
}
if (_isConnecting)
{
return false;
}
_isConnecting = true;
await HubConnection.StartAsync();
Console.WriteLine(@"Connected!");
return true;
}
catch (Exception ex)
{
ExceptionHandler.LogException(ex);
return false;
}
finally
{
_isConnecting = false;
}
}
public async Task<bool> DisconnectAsync()
{
try
{
if (HubConnection.State == HubConnectionState.Disconnected)
{
return true;
}
await HubConnection.StopAsync();
Console.WriteLine(@"Disconnected!");
return true;
}
catch (Exception ex)
{
ExceptionHandler.LogException(ex);
return false;
}
}
private string CreateHubUrl()
{
string accessToken = _accessTokenManager.AuthenticateResult.EncryptedAccessToken;
return ApiUrlConfig.BaseUrl +
AppConsts.SignalRAbpCommonHubPath.TrimStart('/')
+ "?" +
AppConsts.EncryptedAuthTokenQueryStringName + "=" +
Uri.EscapeDataString(accessToken);
}
}`
Could you please help me?
Thank you in advance!
14 Answer(s)
-
0
Hi,
- Did you start the host app using the bat file included under YourPRojectName.Host/ folder ?
- Could you also share the result of CreateHubUrl method ?
Thanks,
-
0
Hi,
and from Web.Host Logs I get DEBUG 2022-11-09 09:16:49,918 [29 ] Abp.AspNetCore.SignalR.Hubs.AbpCommonHub - A client is connected: {"ConnectionId":"OT1w2usalDZHMcb4OoyyCQ","IpAddress":"127.0.0.1","TenantId":1,"UserId":3,"ConnectTime":"2022-11-09T09:16:49.9163277+02:00","Properties":{}}
I send the notification using the below function in AppNotifier when I create a new object
public async Task NewIncidentAsync(Incident incident) { var notificationData = new MessageNotificationData("New " + incident.Criticality.ToString() + " " + incident.Type.ToString() + " incident:" + incident.Description); notificationData["description"] = incident.Description; notificationData["type"] = incident.Type.ToString(); notificationData["critical"] = incident.Criticality.ToString(); notificationData["lat"] = incident.Latitude; notificationData["lon"] = incident.Longitude; notificationData["id"] = incident.Id; await _notificationPublisher.PublishAsync(AppNotificationNames.NewIncident, notificationData,severity: NotificationSeverity.Warn); }
but maybe I do something wrong in message subscription code.
HubConnection.On<string>(AppNotificationNames.NewIncident, (message) => { Console.WriteLine("TEST"); });
Thank you!
-
0
Hi,
Thanks, running the app using Mobile profile is also fine. Could you also share your Hub configuration in your Startup.cs file ?
-
0
Hi,
I have not change anything else about hub configuration. In Web.Host Startup.cs I have the default code. app.UseEndpoints(endpoints => { endpoints.MapHub<AbpCommonHub>("/signalr"); endpoints.MapHub<ChatHub>("/signalr-chat"); ... I may not have understood something correctly about how Notifications work. I have not implemented a separate hub. Do the notifications send a message to the AbpCommonHub signalr hub? If there was a sample or some code on how i can get them in xamarin application that would be great.
Thank you!
-
0
Hi @mgc
Sorry for my late reply. Actaully your approach seems fine. But, could you create a new hub similar to
endpoints.MapHub<ChatHub>("/signalr-chat");
and use it in your Xamarin app as well and send the notification using this hub similar to https://github.com/aspnetzero/aspnet-zero-core/blob/dev/aspnet-core/src/MyCompanyName.AbpZeroTemplate.Web.Core/Chat/SignalR/SignalRChatCommunicator.cs#L46 and see if it works ? -
0
Hi,
I created a new separate hub with a new signalr communicator similar to SignalRChatCommunicator. I modified the Startup with the new endpoint of the new hub. Also I created a new console application in order to test the code and subscribe to then event of the new hub. I manage to connect to the new hub (I checked the log for the connection id) running Host in Mobile profile but I cannot get the message.
I send a message to all clients of the hub using the code below await _incHub.Clients.All.SendAsync("getIncidentMessage", "test");
The code of the console application is `var hubConnection = new HubConnectionBuilder() .WithUrl("https://localhost:44301/inchub", (opts) => { opts.HttpMessageHandlerFactory = (message) => { if (message is HttpClientHandler clientHandler) // bypass SSL certificate clientHandler.ServerCertificateCustomValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return true; }; return message; }; } ) .Build();
hubConnection.On("getMessage", message => Console.WriteLine(message)); hubConnection.On("getIncidentMessage", message => Console.WriteLine(message)); hubConnection.On("App.NewIncident", message => Console.WriteLine(message)); hubConnection.StartAsync().Wait();`
Could you please provide a sample code like the code above that works with any message in default hub or chathub of the asp.net zero. If I had the implementation in Xamarin would be perfect.
I cannot find a solution that works.
Thank you one more time for your help.
-
0
Hi @mgc
Thanks for the update. We will check it deeply and inform you.
-
0
Hi @mgc
I tried to subscribe
getChatMessage
at signalr-chat hub. I can send and receive messages from Angular to Xamarin app. I hope this code helps to you.public async Task<bool> ConnectAsync() { ChatConnection.On<ChatMessageDto>("getChatMessage", (result) => { Console.WriteLine("Helo"); }); try { if (ChatConnection.State == HubConnectionState.Connected) { return true; } if (_isConnecting) { return false; } _isConnecting = true; await ChatConnection.StartAsync(); Console.WriteLine(@"Connected!"); return true; } catch (Exception ex) { ExceptionHandler.LogException(ex); return false; } finally { _isConnecting = false; } } public async Task<bool> SendMessageAsync(string message) { if (!await ConnectAsync()) { return false; } try { var messageData = new SendChatMessageInput { TenantId = 1, UserId = 2, Message = message, }; var response = await ChatConnection.InvokeAsync<string>("SendMessage", messageData); if (string.IsNullOrEmpty(response)) { Console.WriteLine(@"Message successfully sent!"); return true; } Console.WriteLine(@"Message failed to send: " + response); return true; } catch (Exception ex) { ExceptionHandler.LogException(ex); return false; } }
-
0
Hi m.aliozkaya,
Thank you very much for your help and your code.
I used the chathub and your code and I managed to send a message from xamarin to web mvc application and at the same time the On<ChatMessageDto> was called when I sent the message from Xamarin.
But when I send a chat message from the mvc web application then the xamarin application does not receive it. On web mvc application I can send a chat message from one user to another.
Please note that I do not use Angular but MVC.
Any help would be appreciated. Thank you once more!
-
0
Hi @mgc
Is your final CreateHubUrl contains
enc_auth_token
query string parameter with a valid encrpyed token ? -
0
Hi ismcagdas,
Yes, the CreateHubUrl contains the enc_auth_token. Please see the screenshot below from the Host log.
I can send the message successfully from Xamarin to Web app but I cannot receive a message from Web app.
This is my code for the notification service:
public class NotificationService : ISingletonDependency, INotificationService { public HubConnection _HubConnection { get; } private readonly IAccessTokenManager _accessTokenManager; private bool _isConnecting; public NotificationService(IAccessTokenManager accessTokenManager) { try { _accessTokenManager = accessTokenManager; _HubConnection = new HubConnectionBuilder() .WithUrl(CreateHubUrl(), (opts) => { opts.HttpMessageHandlerFactory = (message) => { if (message is HttpClientHandler clientHandler) // bypass SSL certificate clientHandler.ServerCertificateCustomValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return true; }; return message; }; } ) .Build(); _HubConnection.Closed += TryToConnectIfNeeds; } catch (Exception ex) { ExceptionHandler.LogException(ex); } } private async Task TryToConnectIfNeeds(Exception connectionException) { try { ExceptionHandler.LogException(connectionException); if (!_accessTokenManager.IsUserLoggedIn) { return; } await Task.Delay(new Random().Next(0, 5) * 1000); await _HubConnection.StartAsync(); } catch (Exception ex) { ExceptionHandler.LogException(ex); } } public async Task<bool> SendMessageAsync(string message) { if (!await ConnectAsync()) { return false; } try { //find an existing user, I picked the user with Id:4 var messageData = new SendChatMessageInput { TenantId = 1, TenancyName = "Default", UserId = 2, UserName = "admin", Message = message }; var response = await _HubConnection.InvokeAsync<string>("SendMessage", messageData); if (string.IsNullOrEmpty(response)) { Console.WriteLine(@"Message successfully sent!"); return true; } Console.WriteLine(@"Message failed to send: " + response); return true; } catch (Exception ex) { ExceptionHandler.LogException(ex); return false; } } public async Task<bool> ConnectAsync() { _HubConnection.On<ChatMessageDto>("getChatMessage", (result) => { Console.WriteLine("Helo"); }); try { if (_HubConnection.State == HubConnectionState.Connected) { return true; } if (_isConnecting) { return false; } _isConnecting = true; await _HubConnection.StartAsync(); Console.WriteLine(@"Connected!"); return true; } catch (Exception ex) { ExceptionHandler.LogException(ex); return false; } finally { _isConnecting = false; } } public async Task<bool> DisconnectAsync() { try { if (_HubConnection.State == HubConnectionState.Disconnected) { return true; } await _HubConnection.StopAsync(); Console.WriteLine(@"Disconnected!"); return true; } catch (Exception ex) { ExceptionHandler.LogException(ex); return false; } } private string CreateHubUrl() { string accessToken = _accessTokenManager.AuthenticateResult.EncryptedAccessToken; return ApiUrlConfig.BaseUrl + AppConsts.SignalRChatHubPath.TrimStart('/') + "?" + AppConsts.EncryptedAuthTokenQueryStringName + "=" + Uri.EscapeDataString(accessToken); } }
Then inside a view model using a button I call the SendMessageAsync. I might be doing something wrong in how I call and what I call in the class NotificationService above.
Thank you very much for your help!
-
0
Hi @mgc
I think this happens because the default MVC template doesn't handle
enc_auth_token
query string parameter. Could you add this line to your MVC AuthConfigurer class https://github.com/aspnetzero/aspnet-zero-core/blob/dev/aspnet-core/src/MyCompanyName.AbpZeroTemplate.Web.Host/Startup/AuthConfigurer.cs#L57 and also implementQueryStringTokenResolver
in your MVC app ? -
0
Hi ismcagdas,
The above code exists in the Host AuthConfigurer class.
Could you please have a look at the code in the project I am sharing with you in the link below?
https://mgcodegr.sharepoint.com/:u:/g/Ea22k-KFFlVNvWuhI6EnKk8BalPc2UlLMpV1XzjOlS3p_w?e=JpqahC
I have created in the mobile shared the service NotificationService and in the IncidentsViewModel I call the SendMessage which successfully sends the message and the web app receives it but I am not able to receive a message when I send it from the web app.
Thank you very much for your time and your help!
-
0
Hi @mgc ,
We are working on it, we will try to give an answer as soon as possible