3

I'm trying to make Abp notification work. On backend Asp.net boilerplate with asp.net core 2.2 and signalR 1.1.0.

There are several tasks that I need to solve:

1. simple js client without angular(does not work, code below)
2. It is assumed that the signalR sends messages in real time, but how can the Abp handle situations if the user is offline, or has been disconnected at the time of the sending notification? If there is no such functionality in ABP, what can I do about it?
3. Does the ABP have a mechanism to confirm receipt of a notification? Can I be sure that my message has been delivered?

client: install abp-web-resources and get abp.signalr.js + abp.signalr-client.js Index.html looks like:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">    
    <title>Document</title>
</head>
<body>    
    <div id="inputForm">
        <p>Customer ABP client</p>
        <p>Message:</p>
        <input type="text" id="message" />
        <p>User:</p>
        <input type="text" id="user" />
        <input type="button" id="sendBtn" value="send" />       

    </div>
    <div id="chatroom"></div>
    <script   src="https://code.jquery.com/jquery-3.4.1.min.js"
              integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
              crossorigin="anonymous"></script>
    <script src="node_modules/abp-web-resources/Abp/Framework/scripts/libs/abp.signalr.js"></script>
    <script src="node_modules/abp-web-resources/Abp/Framework/scripts/libs/abp.signalr-client.js"></script>
    <script>
        let myUrl = "http://localhost:21021";               
        let hubUrl = "/chat";        
        let token = "Bearer here my token";         

        var chatHub = null;

        abp.signalr.startConnection(myUrl + hubUrl, function (connection) {
            chatHub = connection; 
            connection.on('Send', function (message, userName, connectionId, time) {            
                let userNameElem = document.createElement("b");
                userNameElem.appendChild(document.createTextNode(time +" "+userName+" ("+ connectionId +")"+ ' : '));

                let elem = document.createElement("p");
                elem.appendChild(userNameElem);
                elem.appendChild(document.createTextNode(message));

                let firstElem = document.getElementById("chatroom").firstChild;
                document.getElementById("chatroom").insertBefore(elem, firstElem);     
            }); 
        }).then(function (connection) {
            abp.log.debug('Connected to myChatHub server!');
            abp.event.trigger('myChatHub.connected');
        });

        abp.event.on('myChatHub.connected', function() { 
            chatHub.invoke('sendMessage', "Hi everybody, I'm connected to the chat!"); 
        });

        document.getElementById("sendBtn").addEventListener("click", function (e) {
            let message = document.getElementById("message").value;
            let userName = document.getElementById("user").value;           

            chatHub.invoke("Send", message, userName).catch(function (err) {
                return console.error(err.toString());
            });

            event.preventDefault();
        });
    </script>
</body>
</html>

Startup.cs In ConfigureServices: ...

 services.AddSignalR();            
 services.AddCors(
    options => options.AddPolicy(
                    DefaultCorsPolicyName,
                    builder => builder                         
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowAnyOrigin() 
                        .AllowCredentials()
                ));

...

In Configure:

...
 app.UseAbp(options => { options.UseAbpRequestLocalization = false; });
 app.UseWebSockets();
 app.UseCors(DefaultCorsPolicyName); 
 app.UseStaticFiles();
 app.UseAuthentication();
 app.UseAbpRequestLocalization();

 app.UseSignalR(routes => { routes.MapHub<Test2Hub>("/chat"); });

app.UseMvc();
...

also in AuthConfigurer the token is processed and the authorization header is added (I do not write for short)

My hub:

namespace MyProjectName.Web.Host.MyHubs
{
    [Authorize]
    public class Test2Hub : AbpHubBase, ISingletonDependency //with trancient  
                                        //not working at all: Clients == null
    {
        private IAbpSession AbpSession { get; set; }        

        public Test2Hub( )            
        {
            AbpSession = NullAbpSession.Instance;            
        }

        public async Task Send(string msg, string userName)
        {
            await this.Clients.All.SendAsync("Send", msg, userName, Context.ConnectionId, "[" + Clock.Now + "]");
        }

        public async Task SendToUser(string msg, long userId)
        {
            if (this.Clients != null)
            {
                await Clients.User(userId.ToString()).SendAsync("Send", msg, "From Server by userID ",   Context.ConnectionId, Clock.Now);
            }
            else
            {
                throw new UserFriendlyException("smthng wrong");                
            }           
        }

        public async Task<HttpContext> GetContext()
        {
            return Context.GetHttpContext();
        }

        public override async Task OnConnectedAsync()
        {            
            await Clients.All.SendAsync("Send", $"{Context.UserIdentifier} enter into chat");
            await base.OnConnectedAsync();
        }

        public override async Task OnDisconnectedAsync(Exception exception)
        {            
            await Clients.All.SendAsync("Send", $"{Context.UserIdentifier} gone...");
            await base.OnDisconnectedAsync(exception);
        }        
    }
}

Controller:

 [Route("api/[controller]/[action]")]
    public class NotificationWebController : MyProjectControllerBase, IRealTimeNotifier
    {        
        private readonly Test2Hub _testHub;       
        private readonly INotificationPublisher _notificationPublisher;
        private readonly INotificationSubscriptionManager _notificationSubscriptionManager;
        private readonly IUserNotificationManager _notificationManager;

        public NotificationWebController
        (
            IUserNotificationManager notificationManager,
            INotificationPublisher notificationPublisher,
            INotificationSubscriptionManager notificationSubscriptionManager,
            Test2Hub testHub            
        )
        {
            _testHub = testHub;
            _notificationPublisher = notificationPublisher;
            _notificationSubscriptionManager = notificationSubscriptionManager;
            _notificationManager = notificationManager;
        }

        [HttpPost]
        public async Task SendToUserBySignalR(string msg, long userId)
        {                           
            await _testHub.SendToUser(msg, userId);            
        }

        [HttpGet]
        public async Task<HttpContext> GetContext()
        {            
            return await _testHub.GetContext();            
        }

         /*
            I also tried to use the Abp notification system,
 records in the database were created, but I could not transfer it to the client
        */        

        [HttpPost]
        public async Task Subscribe(int? tenantId, long userId)
        {
            await _notificationSubscriptionManager.SubscribeAsync(new UserIdentifier(tenantId, userId), "App.SimpleMessage");
        }

        [HttpPost]
        public async Task<ActionResult> TestNotificationAbp(string message, long userId)
        {    
            var identifier = new UserIdentifier(1, userId); //tenantId = 1
            await _notificationPublisher.PublishAsync(
                "App.SimpleMessage",
                new MessageNotificationData(message),
                severity: NotificationSeverity.Info,
                userIds: new[] { identifier }
            );

            return Content("Sent notification: " + message);
        }  

        [HttpPost]
        public async Task SendNotificationsAsync(UserNotification[] userNotifications)
        {
            //realization IRealTimeNotifier, but it is not clear how to use it...
           throw new NotImplementedException();
        }                
    }

client not work. Errors:

abp.signalr-client.js:5 Uncaught ReferenceError: signalR is not defined
    at abp.signalr-client.js:5
    at abp.signalr-client.js:109
(anonymous) @ abp.signalr-client.js:5
(anonymous) @ abp.signalr-client.js:109
(index):38 Uncaught TypeError: Cannot read property 'startConnection' of undefined 

What am I doing wrong? I would also appreciate answers to the questions described above. And sorry for my English.

Goliath2019
  • 97
  • 1
  • 8
  • Possible duplicate of https://stackoverflow.com/questions/22197129/how-to-do-guaranteed-message-delivery-with-signalr – ryan.c Jun 15 '19 at 05:33

1 Answers1

1
<script src="node_modules/abp-web-resources/Abp/Framework/scripts/libs/abp.signalr.js"></script>
<script src="node_modules/abp-web-resources/Abp/Framework/scripts/libs/abp.signalr-client.js"></script>

ASP.NET Core

Use abp.signalr-client.js, which depends on signalr.js.

<script src="node_modules/signalr/dist/browser/signalr.js"></script>
<script src="node_modules/abp-web-resources/Abp/Framework/scripts/libs/abp.signalr-client.js"></script>

References:

ASP.NET MVC 5

Use abp.signalr.js, which depends on signalr/hubs.

<script src="signalr/hubs"></script>
<script src="node_modules/abp-web-resources/Abp/Framework/scripts/libs/abp.signalr-client.js"></script>

References:

aaron
  • 39,695
  • 6
  • 46
  • 102