Skip to content

Instantly share code, notes, and snippets.

@XSockets
Last active December 25, 2015 02:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save XSockets/6900894 to your computer and use it in GitHub Desktop.
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
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; }
}
}
<!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>
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");
}
}
}
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);
}
}
}
}
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