Уведомление ABP с SignalR и простым клиентом JS - PullRequest
0 голосов
/ 11 июня 2019

Я пытаюсь заставить работать уведомление Abp. На серверной части Asp.net с ядром asp.net 2.2 и сигналом R 1.1.0.

Есть несколько задач, которые мне нужно решить:

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?

клиент: установите abp-web-ресурсы и получите abp.signalr.js + abp.signalr-client.js Index.html выглядит так:

<!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 В ConfigureServices: ...

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

...

В конфигурации:

...
 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();
...

также в AuthConfigurer обрабатывается токен и добавляется заголовок авторизации (я не пишу для краткости)

Мой хаб:

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);
        }        
    }
}

Контроллер:

 [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();
        }                
    }

клиент не работает. Ошибки:

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 

Что я делаю не так? Буду также признателен за ответы на вопросы, описанные выше. И извините за мой английский.

...