Last active
December 25, 2015 02:09
-
-
Save XSockets/6900894 to your computer and use it in GitHub Desktop.
A simple example on how to setup a notification system with XSockets.NET. The idea came from this question on Stackoverflow: http://stackoverflow.com/questions/19251699/invoke-popup-as-reminder-in-asp-net-mvc/19252198#19252198
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
namespace XNotify | |
{ | |
public class Appointment | |
{ | |
/// <summary> | |
/// Id of the appointment | |
/// </summary> | |
public Guid Id { get; set; } | |
/// <summary> | |
/// The StorageGuid of the owner (unique for each client, like a session id... kind of) | |
/// </summary> | |
public Guid StorageGuid { get; set; } | |
/// <summary> | |
/// The headline for the appointment | |
/// </summary> | |
public string Subject { get; set; } | |
/// <summary> | |
/// A little bit more information about the appointment | |
/// </summary> | |
public string Details { get; set; } | |
/// <summary> | |
/// The time when the appointment starts | |
/// </summary> | |
public DateTime Time { get; set; } | |
/// <summary> | |
/// How many minutes does the meeting last | |
/// </summary> | |
public int Duration { get; set; } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html xmlns="http://www.w3.org/1999/xhtml"> | |
<head> | |
<title></title> | |
<script src="Scripts/jquery-1.9.1.js"></script> | |
<script src="Scripts/XSockets.latest.js"></script> | |
<script src="Scripts/knockout-2.3.0.js"></script> | |
<!-- For easy convert to .NET datetime //--> | |
<script src="Scripts/moment.js"></script> | |
<script> | |
var conn = undefined; | |
//ViewModel | |
var VM = { | |
Notifications:ko.observableArray() | |
}; | |
$(function () { | |
//Activate knockout | |
ko.applyBindings(VM); | |
//create a connection | |
conn = new XSockets.WebSocket('ws://127.0.0.1:4502/Notifier'); | |
conn.on(XSockets.Events.open, function() { | |
//Connection open | |
//subscribe to Notify event | |
conn.on('notify', function(n) { | |
//Your logic here... Show a notification and play a sound... | |
//I just output it to the viewmodel | |
VM.Notifications.unshift(n); | |
}); | |
//Add a new appointment... | |
$('#btn-save-appointment').on('click', function() { | |
//Add a fake that occurs in x minutes where x is the value of our input-timer | |
conn.publish('addappointment', {Subject:'Fake Subject',Details:'Fake Details....',Duration:10, Time:moment().add('minutes',$('#input-timer').val()).format("YYYY-MM-DD HH:mm:ss")}); | |
}); | |
}); | |
}); | |
</script> | |
</head> | |
<body> | |
<label>Minutes from now until the start of the meeting...</label> | |
<input id="input-timer" type="number" min="1" max="10" step="1" value="1" /><br/> | |
<button id="btn-save-appointment">Add Appointment</button> | |
<hr/> | |
If you are offline (not on the page) and an notification is sent to you you will still get it as long as you are back within 5 minutes...<br/> | |
Read server side code for more info... | |
<hr/> | |
<div id="notifications" data-bind="foreach:Notifications"> | |
<div> | |
<h4 data-bind="text:Subject"></h4> | |
<span data-bind="text:Details"></span> | |
</div> | |
</div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using XSockets.Core.Utility.Storage; | |
using XSockets.Core.XSocket; | |
using XSockets.Core.XSocket.Helpers; | |
namespace XNotify | |
{ | |
/// <summary> | |
/// A controller (plugin) that will take care of all notificaitons. | |
/// | |
/// Mission | |
/// Users create appointments and should be notified x minutes before the appointment | |
/// | |
/// Challenges | |
/// 1 Keep track of appointments and when they occur | |
/// 2 Keep state between connections for all appointments per client | |
/// 3 When an reminder fires send the message to the correct client | |
/// 4 If the client is offline (maybe between pages) the message should be stored and sent when the client gets back online. | |
/// </summary> | |
public class Notifier : XSocketController | |
{ | |
public Notifier() | |
{ | |
this.OnClientConnect += Notify_OnClientConnect; | |
this.OnClientDisConnect += Notify_OnClientDisConnect; | |
} | |
void Notify_OnClientDisConnect(object sender, XSockets.Core.Common.Socket.Event.Arguments.OnClientDisConnectArgs e) | |
{ | |
//Tell XSockets to store messages for me while I am offline | |
//We store them for 5 minutes and the messages we store is only for the Notify event | |
this.OfflineSubscribe(300000,"Notify"); | |
} | |
void Notify_OnClientConnect(object sender, XSockets.Core.Common.Socket.Event.Arguments.OnClientConnectArgs e) | |
{ | |
//Get messages that arrived while I was offline | |
this.OnlinePublish(); | |
} | |
/// <summary> | |
/// Register a new appointment that will send a notification to the client x minutes before | |
/// </summary> | |
/// <param name="appointment"></param> | |
public void AddAppointment(Appointment appointment) | |
{ | |
//Just add id´s... | |
appointment.StorageGuid = this.StorageGuid; | |
appointment.Id = Guid.NewGuid(); | |
//Add to storage so that the NotifierEngine can find it... | |
Repository<Guid, Appointment>.AddOrUpdate(appointment.Id, appointment); | |
} | |
/// <summary> | |
/// Send a notification to the client, will be called from the notifierengine... | |
/// </summary> | |
/// <param name="appointment"></param> | |
public void Notify(Appointment appointment) | |
{ | |
//Use a custom extension to also queue messages if the user is offline | |
this.SendAndQueue(p => p.StorageGuid == appointment.StorageGuid, appointment, "Notify"); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Timers; | |
using XSockets.Core.Common.Globals; | |
using XSockets.Core.Common.Socket; | |
using XSockets.Core.Utility.Storage; | |
using XSockets.Core.XSocket; | |
using XSockets.Plugin.Framework.Core; | |
namespace XNotify | |
{ | |
/// <summary> | |
/// This is a longrunning contorller in XSockets... | |
/// In here we can handle stuff like polling for data or longrunning tasks.. | |
/// Clients cant connect to this controller.... | |
/// </summary> | |
[XBaseSocketMetadata("NotifyEngine", Constants.GenericTextBufferSize, PluginRange.Internal)] | |
public class NotifyEngine : XSocketController | |
{ | |
private static Notifier notifier; | |
private static Timer timer; | |
static NotifyEngine() | |
{ | |
//Initialize your long running stuff here | |
notifier = new Notifier(); | |
//Start a timer thar ticks every second... | |
timer = new Timer(1000); | |
timer.Elapsed += timer_Elapsed; | |
timer.Start(); | |
} | |
/// <summary> | |
/// On tick we check if there are any appointments that needs to be sent... | |
/// We will send a notification 10 seconds before the meeting.. Hurry up ;) | |
/// </summary> | |
/// <param name="sender"></param> | |
/// <param name="e"></param> | |
static void timer_Elapsed(object sender, ElapsedEventArgs e) | |
{ | |
var appointments = Repository<Guid, Appointment>.Find(p => p.Time.AddSeconds(-10) <= DateTime.Now); | |
foreach (var appointment in appointments) | |
{ | |
//Notify client | |
notifier.Notify(appointment); | |
//Remove appointment | |
Repository<Guid, Appointment>.Remove(appointment.Id); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using XSockets.Core.Common.Socket; | |
using XSockets.Core.XSocket; | |
using XSockets.Core.XSocket.Helpers; | |
namespace XNotify | |
{ | |
/// <summary> | |
/// Custom extension for this sample | |
/// </summary> | |
public static class XSocketsHelper | |
{ | |
/// <summary> | |
/// A helper for both sending to those online and storing for those offline... | |
/// </summary> | |
/// <typeparam name="T"></typeparam> | |
/// <param name="socket"></param> | |
/// <param name="condition"></param> | |
/// <param name="o"></param> | |
/// <param name="eventname"></param> | |
public static void SendAndQueue<T>(this T socket, Func<T, bool> condition, object o, string eventname) | |
where T : XBaseSocket, IXBaseSocket | |
{ | |
//Send to onliners | |
socket.SendTo(condition, o, eventname); | |
//Queue message for offliners | |
socket.Queue(socket.ToTextArgs(o,eventname), condition); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment