Push-уведомления для конкретных пользователей или устройств - PullRequest
0 голосов
/ 31 октября 2018

У меня есть система WEB MVC 5, в которой я использую signalR и SqlDependency для работы в режиме реального времени, но это не тот случай, когда мне нужно реализовать push-уведомления для системных администраторов, когда происходят изменения интереса. Если говорить конкретно, мне нужен механизм для отправки push-уведомлений определенным пользователям и, если возможно, даже если они не подключены, то есть даже если они не используют систему.

Я много искал, я использовал библиотеку push.js, но это не позволяет мне сделать это, или я так думаю.

Будет получен любой механизм, который может обеспечить мои потребности или что-то подобное.

1 Ответ

0 голосов
/ 02 ноября 2018

Я написал хранимую процедуру (SP), которая возвращает сведения о событии в соответствии с пользователем. Вы можете создать таблицу, в которой хранится идентификатор, по которому вы хотите отправить уведомление, и каждая вставка в эту таблицу будет уведомлять пользователя.

У меня есть три таблицы: «Пользователь», «События», «Пользовательские события». В таблице UserEvents есть идентификатор пользователя в качестве внешнего ключа из таблицы пользователей и идентификатор события в качестве внешнего ключа из таблицы событий. В моей системе, когда событие вставлено в таблицы выше, signalR выполняет свою работу. Таблица UserEvents имеет следующие столбцы:

   [Uev_ID]
  ,[Uev_UserID]
  ,[Uev_EventID]
  ,[Uev_IsRead]
  ,[Uev_ReadDate]
  ,[GuID]
  ,[Deleted]

Модель моего события, как показано ниже:

    public class EventList
    {
    public Int64 EventID { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public DateTime Date { get; set; }
    public string Color { get; set; }
    }

Должен существовать репозиторий сообщений для взаимодействия и связи с базой данных и моделью. Этот репозиторий будет обрабатывать метод dependency_OnChange.

    public class MessagesRepository
    {
    internal static SqlCommand command = null;
    internal static SqlCommand command2 = null;
    internal static SqlDependency dependency = null;
    internal static SqlDependency dependency2 = null;
    readonly string _connString = 
                  ConfigurationManager.ConnectionStrings["signalr"].ConnectionString;
    private Int64 user { get; set; }
    public MessagesRepository(Int64 userID)
    {
        user = userID;
    }

    public IEnumerable<EventList> GetAllMessages()
    {
        var messages = new List<EventList>();
        using (var connection = new SqlConnection(_connString))
        {
            connection.Open();
            using (command = new SqlCommand("[sp_SysEvent]", connection))
            {
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.AddWithValue("@user", user);
                command.Notification = null;

                if (dependency == null)
                {
                    dependency = new SqlDependency(command);
                    dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
                }
                if (connection.State == ConnectionState.Closed)
                    connection.Open();

                var reader = command.ExecuteReader();

                while (reader.Read())
                {
                    messages.Add(item: new EventList { EventID = (Int64)reader["Evt_ID"], Description = (string)reader["Evt_Description"], Title = (string)reader["Evg_Title"], Date = (DateTime)reader["Evt_Date"], Color = (string)reader["Clr_Color"] });
                }
            }
        }
        return messages;
    }

    private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
    {
        if (dependency != null)
        {
            dependency.OnChange -= dependency_OnChange;
            dependency = null;
        }
        if (e.Info == SqlNotificationInfo.Insert)
        {

            TestHub.SendUser(user);
        }
    }
}

Мне понадобился документ сопоставления подключений для отправки уведомлений подключенным пользователям. Когда пользователь подключен, я помещаю его идентификатор в HashSet и удаляю из HashSet, когда пользователь отключается. Вы можете использовать это, чтобы определить, какой пользователь подключен. Вот схема подключения: открытый класс ConnectionMapping { Частный словарь> _connections = новый словарь> ();

    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> GetConnections2(T key)
    //{
    //    List<HashSet<string>> connections;
    //    if (_connections.Any(x => x.Key.ToString().Contains(key.ToString())))
    //    {
    //        connections = _connections.Where(x => x.Key.ToString().StartsWith(key.ToString() + "_")).Select(x => x.Value);
    //    }

    //    return Enumerable.Empty<string>();
    //}
    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);
                }
            }
        }
    }
}

И документ Hub:

public class TestHub : Hub
{
    private readonly static ConnectionMapping<string> _connections = new ConnectionMapping<string>();
    public string GetUserGroup()
    {
        string abc = "";
        using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["signalr"].ConnectionString))
        {
            connection.Open();
            string sqltheme = "Select Usr_GroupID from SysUser where ID=" + Convert.ToInt32(HttpContext.Current.User.Identity.Name.Split('_')[1]) + "";
            using (SqlCommand command = new SqlCommand(sqltheme, connection))
            {
                abc = command.ExecuteScalar().ToString();
            }
        }
        return abc;
    }
    public override Task OnConnected()
    {
        string name = "";
        try
        {
            name = HttpContext.Current.User.Identity.Name.Split('_')[1];
            Groups.Add(Context.ConnectionId, GetUserGroup());
        }catch(Exception ex)
        {
            name = Context.ConnectionId;
        }
        if (_connections.GetConnections(name).Count() > 0)
        {
            _connections.Remove(name, _connections.GetConnections(name).ToString());
        }
        _connections.Add(name, Context.ConnectionId);
        return base.OnConnected();
    }
    [HubMethodName("send")]
    public void Send(string mes)
    {
        Clients.All.send(mes); // if you want to send all user use this.
    }
    [HubMethodName("sendUser")]
    public void SendUser(string[] who, int id, string title)
    {
        string name = Context.User.Identity.Name;
        foreach (var user in who)
        {
            foreach (var connectionId in _connections.GetConnections(user))
            {
                Clients.Client(connectionId).sendUser(id, title);
            }
        }
    }
    }

Наконец, код javascript для вызова функций хаба:

var myhub = $.connection.testHub;
        $(function () {
            $.connection.hub.start();
            chat.client.sendUser = function (id, title) {
                var count = parseFloat($("#header_notification_bar > a > span").text()) + 1;
                $("#header_notification_bar > a > span").text(count);
                toastr.info('Bir Yeni Bildiriminiz Var.Görüntülemek İçin Tıklayınız.', 'Bildirim', {
                    closeButton: true, timeOut: 20000, onclick: function () {
                        window.location.href = '/tr/Notification/List';
                    }
                });
                $("#notification_list").prepend("<li><a href='javascript:;' style='background-color:#e6e6e6' class='okunmadi' id='" + id + "'><span class='time' style='min-width:100px;'>şimdi</span><span class='details'><span class='label label-sm label-icon label-success'><i class='fa fa-bullhorn'></i></span>" + title + "</span></a></li>");
            };

Хотелось бы, чтобы это сработало и у вас.

...