向特定用户或设备推送通知
Push notifications to specific users or devices
我有一个 WEB MVC 5 系统,我在其中实时使用 signalR 和 SqlDependency,但情况并非如此,我需要实现的是在兴趣发生变化时向系统管理员推送通知。具体来说,我需要的是一种向特定用户发送推送通知的机制,如果可能的话,即使他们没有连接,也就是说,即使他们没有使用系统。
我搜索了很多,我正在使用 push.js 库,但这不允许我这样做或者我认为是这样。
任何能够满足我的需求或类似需求的机制都会被接收。
我写了一个存储过程 (SP),其中 returns 根据用户的事件详细信息。您可以创建一个 table 来保留您要发送通知的 ID,每次插入此 table 都会通知用户。
我有三个 table,分别是 'User'、'Events'、'UserEvents'。
在 UserEvents Table 中,userID 作为来自用户 table 的外键,eventID 作为来自事件 table 的外键。在我的系统中,当事件插入到上面的 tables 时,signalR 会完成它的工作。
UserEvents Table 具有如下列:
[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);
}
}
}
我需要一个连接映射文档来向连接的用户发送通知。当用户连接时,我将其 ID 放入 HashSet 并在用户断开连接时从 HashSet 中删除。您可以使用它来检测哪个用户已连接。
这是连接映射:
public class 连接映射
{
private Dictionary> _connections = new Dictionary>();
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>");
};
我希望它也适合你。
我有一个 WEB MVC 5 系统,我在其中实时使用 signalR 和 SqlDependency,但情况并非如此,我需要实现的是在兴趣发生变化时向系统管理员推送通知。具体来说,我需要的是一种向特定用户发送推送通知的机制,如果可能的话,即使他们没有连接,也就是说,即使他们没有使用系统。
我搜索了很多,我正在使用 push.js 库,但这不允许我这样做或者我认为是这样。
任何能够满足我的需求或类似需求的机制都会被接收。
我写了一个存储过程 (SP),其中 returns 根据用户的事件详细信息。您可以创建一个 table 来保留您要发送通知的 ID,每次插入此 table 都会通知用户。
我有三个 table,分别是 'User'、'Events'、'UserEvents'。 在 UserEvents Table 中,userID 作为来自用户 table 的外键,eventID 作为来自事件 table 的外键。在我的系统中,当事件插入到上面的 tables 时,signalR 会完成它的工作。 UserEvents Table 具有如下列:
[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);
}
}
}
我需要一个连接映射文档来向连接的用户发送通知。当用户连接时,我将其 ID 放入 HashSet 并在用户断开连接时从 HashSet 中删除。您可以使用它来检测哪个用户已连接。 这是连接映射: public class 连接映射 { private Dictionary> _connections = new Dictionary>();
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>");
};
我希望它也适合你。