M
M
Mikhail Plyusnin2016-03-10 08:34:40
JavaScript
Mikhail Plyusnin, 2016-03-10 08:34:40

Push notifications on the site?

Good morning everyone, I want to make push notifications on a news site (the project is written in ASP .NET MVC). I want that when a registered user adds news, the site admin or moderator will hear a sound signal and pop up a notification that new news has been added and should be checked and approved.

  • What is the best way to do this?

While I look towards SignalR .
  • Can this library cope with my Wishlist?
  • My misunderstanding is the following, how do I determine exactly those people to whom I should send this notification? Because in the examples with which I worked, I did not find anything like that.

Answer the question

In order to leave comments, you need to log in

3 answer(s)
M
Mikhail Plyusnin, 2016-03-11
@rpe4a

In general, thanks to everyone for the advice, but amf1k turned out to be the closest . After looking and studying the documentation on

  • Next, add SignalR itself to your project via Nuget;
  • We attach it to the project;
  • Create a client script (I put it in a separate file and made a link to it on the page):
    $(function () {
       //определяем наш хаб
        var hub = $.connection.notificationHub;
        //метод хаба на клиенте, который будет вызван у всех подключенных клиентов, когда ему будет дана команда с сервера
        hub.client.sendNotification = function (message) {
            //выводим сообщение подключенным клиентам(в моем случае это будут только админы)
            $("#hubMessageConteiner")
                .append("<li>" + message + "<i title='Закрыть' class='fa fa-close fa-lg cursor-pointer'></i></li>")
                .find("li").show(200);
        };
        //создаем подключение к хабу, это метод start, если пользователь смог подключится к хабу, то вызывается функция done, если нет то будет вызываться функция fail
        $.connection.hub.start().done(function () {
            $('#Hub').click(function () {
                hub.server.send("Это push уведомление");
            });
        });
    });

  • We create our own Hub-class on the backend that will process these notifications, to store information about those connecting to the hub, I used the Memory storage approach :
    public class NotificationHub:Hub
        {
    //хранилище подключений(тут я храню только администраторов)
            private readonly static ConnectionMapping<string> _connections = new ConnectionMapping<string>();
    
    //сейчас я вызываю этот метод с клиента, но его легко можно и вызвать на сервере, 
    //допустим в каком-нибудь методе контроллера, что я в последствии и собираюсь сделать,
    //потому что мне надо, чтобы при добавлении новости уведомления получал только администратор или модератор
            public void Send(string message)
            {
    
                var user = Context.User;
    //получаем всех подключенных админов и каждому отправляем уведомление
                foreach (var connectionId in _connections.GetConnections())
                {
    //если это сам админ то не надо отправлять
                    if (!user.IsAdmin())
                    {
    //тут мы вызываем метод на клиенте, который и отобразит наше уведомление
                        Clients.Client(connectionId).sendNotification(message);
                    }
                }
            }
    
            public override Task OnConnected()
            {
    //Хаб имеет доступ к контексту + я использую Identity (ссылку дал выше читайте), следовательно могу получить доступ к информации о подключенном пользователе:
                var user = Context.User;
    
                if (user.IsAdmin())
                {
                    string userId = Context.User.GetUserId();
    //запихиваем нашего подключенного пользователя если он админ в хранилище подключений, кстати каждому подключившемуся выдается ConnectionId, который можно получить из контекста и да он уникален и выдается каждый раз новый при подключении
                    _connections.Add(userId, Context.ConnectionId);
                }
                return base.OnConnected();
            }
    
            public override Task OnDisconnected(bool stopCalled)
            {
                var user = Context.User;
    
                if (user.IsAdmin())
                {
                    string userId = user.GetUserId();
    //если пользователь(админ) отключился, то убираем его из хранилища
                    _connections.Remove(userId, Context.ConnectionId);
                }
    
                return base.OnDisconnected(stopCalled);
            }
    
            public override Task OnReconnected()
            {
                var user = Context.User;
    
                if (user.IsAdmin())
                {
                    string userId = user.GetUserId();
    
                    if (!_connections.GetConnections(userId).Contains(Context.ConnectionId))
                    {
                        _connections.Add(userId, Context.ConnectionId);
                    }
                }
    
                return base.OnReconnected();
            }
        }
    
    //на всякий случай добавлю класс хранилища подключений, но он такой же как в документации
    public class ConnectionMapping<T>
        {
            private readonly Dictionary<T, HashSet<string>> _connections = new Dictionary<T, HashSet<string>>();
    
            public int Count
            {
                get
                {
                    return _connections.Count;
                }
            }
    
            public void Add(T key, string connectionId)
            {
                lock (_connections)
                {
                    HashSet<string> connections;
                    if (!_connections.TryGetValue(key, out connections))
                    {
                        connections = new HashSet<string>();
                        _connections.Add(key, connections);
                    }
    
                    lock (connections)
                    {
                        connections.Add(connectionId);
                    }
                }
            }
    
            public IEnumerable<string> GetConnections(T key)
            {
                HashSet<string> connections;
                if (_connections.TryGetValue(key, out connections))
                {
                    return connections;
                }
    
                return Enumerable.Empty<string>();
            }
    //добавил только вот этот метод для получения всех подключивщихся администраторов
            public IEnumerable<string> GetConnections()
            {
                HashSet<string> connections = new HashSet<string>();
    
                if (_connections.Any())
                {
                    foreach (var connection in _connections)
                    {
                        foreach (var connectionId in connection.Value)
                        {
                            connections.Add(connectionId);
                        }
                    }
                }
    
                return connections;
            }
    
            public void Remove(T key, string connectionId)
            {
                lock (_connections)
                {
                    HashSet<string> connections;
                    if (!_connections.TryGetValue(key, out connections))
                    {
                        return;
                    }
    
                    lock (connections)
                    {
                        connections.Remove(connectionId);
    
                        if (connections.Count == 0)
                        {
                            _connections.Remove(key);
                        }
                    }
                }
            }
        }

  • Well, actually everything. It works for me, when you click on the test button, a notification is sent to all admins. All the best and have a good day ;
  • A
    amf1k, 2016-03-10
    @amf1k

    1) Yes, it can.
    2) Here you can look, maybe you will find something. So overall, it all depends on how you set it up.

    O
    Oleg Karnaukhov, 2016-03-11
    @BupycNet

    You can use PushAll. There is support for smartphone computers, there are notifications on telegrams, you can duplicate them in the mail.
    You can send notifications to individual users while the site tabs can be closed.
    For android there are sound and vibration settings. Chrome has missed notifications and widget to view history

    Didn't find what you were looking for?

    Ask your question

    Ask a Question

    731 491 924 answers to any question