SignalR is a Microsoft library still in pre release.
https://github.com/SignalR/SignalR
With SignalR we can implement the HTML5 WebSocket without worrying that the web server or the browser supports it. We can do this because the library itself will use long polling or classic polling as an alternative.
This technology finds its expression in chat rooms or online games, but we can think about health information systems, such as notifications to clients of alarms related to the results of laboratories (ok, I did not fancy, it's only my job :-) )
In this post we realize a system of push notifications in VB.Net updated to the latest release of SignalR, at least for now.
Step 1
First open visual studio 2012 and select new project: ASP.NET Empty web application.
Install gituhub Package from Package Manager Console
PM> Install-Package Microsoft.AspNet.SignalR
Step 2
Add a new Class to project and create a PersistantConnection:
Imports System.Threading.Tasks
Imports Microsoft.AspNet.SignalRPublic Class NotificationConnectionInherits PersistentConnectionProtected Overrides Function OnConnected(request As IRequest, connectionId As String) As System.Threading.Tasks.TaskReturn MyBase.OnConnected(request, connectionId)End FunctionEnd Class
Step 3
Add our class for notifications (for simplicity we create the note with a value and a time):
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
RouteTable.Routes.MapConnection(Of NotificationConnection("NotificationConnection","/NotificationConnection")
Task.Factory.StartNew(Function()
Dim connectonManager As IConnectionManager =GlobalHost.DependencyResolver.Resolve(Of IConnectionManager()
Dim connection = connectonManager.GetConnectionContext(Of NotificationConnection)()
While True
Dim item = New Notification() With { _
.Data = DateTime.Now.ToString("hh:mm:ss"), _
.ExamValue= CInt(Math.Ceiling(Rnd() * 100))
'/* For simplicity we simulate the result of examination with a randomic value }
connection.Connection.Broadcast(item)
Thread.Sleep(1000)
End While
End Function)
End Sub
Imports Microsoft.AspNet.SignalR
Public Class NotificationPrivate _ExamValue As Int32Private _Data As StringPublic Property ExamValue As Int32GetReturn _ExamValueEnd GetSet(value As Int32)_ExamValue = valueEnd SetEnd PropertyPublic Property Data As StringGetReturn _DataEnd GetSet(value As String)_Data = valueEnd SetEnd PropertyEnd Class
Step 4
Critical step, the addition of the file Global.asax.vb, it specializes our router, which will do the job right at the time when the client creates a connection to the server
RouteTable.Routes.MapConnection(Of NotificationConnection("NotificationConnection","/NotificationConnection")
Task.Factory.StartNew(Function()
Dim connectonManager As IConnectionManager =GlobalHost.DependencyResolver.Resolve(Of IConnectionManager()
Dim connection = connectonManager.GetConnectionContext(Of NotificationConnection)()
While True
Dim item = New Notification() With { _
.Data = DateTime.Now.ToString("hh:mm:ss"), _
.ExamValue= CInt(Math.Ceiling(Rnd() * 100))
'/* For simplicity we simulate the result of examination with a randomic value }
connection.Connection.Broadcast(item)
Thread.Sleep(1000)
End While
End Function)
End Sub
Step 5
Now we move on the client and build our html page:
<script src="scripts/jquery-1.6.4.js" type="text/javascript"></script>
<script src="scripts/json2.js" type="text/javascript"></script>
<script src="scripts/jquery.signalR-1.1.1.js" type="text/javascript"></script>
<script type="text/javascript">
var output;
$(document).ready(function () {
output = $("#output");
});
var data;
var options;
connection = $.connection('/NotificationConnection');
connection.received(function (dataItem) {
var newItem = dataItem;
output.text("Received exam value: " + newItem.Data + "," + newItem.ExamValue);
});
connection.start();
</script>
<body>
<h2>Laboratory Exams Monitoring</h2>
<div id="output"></div>
</body>
That's it, from now our good server will update us every second with the value of the exam to be observed, we can think to plot the trend or change the Application_Start() to retrieve values from the laboratory and just update us in case of alert.
Step 4 generates some errors on "NotificationConnection"
ReplyDeleteI do not have any problems, you can be more accurate so I try to help you?
ReplyDeletesame with Yücel, i got errors on step 4,
ReplyDeleteon this line
RouteTable.Routes.MapConnection(Of NotificationConnection("NotificationConnection","/NotificationConnection")
i even try
RouteTable.Routes.MapConnection(Of NotificationConnection("NotificationConnection"),"/NotificationConnection")
and i got this error message
Overload resolution failed because no accessible 'StartNew' can be called with these arguments:
'Public Function StartNew(Of TResult)(function As System.Func(Of TResult)) As System.Threading.Tasks.Task(Of TResult)': Type 'IConnectionManager' is not defined.
'Public Function StartNew(Of TResult)(function As System.Func(Of TResult)) As System.Threading.Tasks.Task(Of TResult)': 'Thread' is not declared. It may be inaccessible due to its protection level.
'Public Function StartNew(Of TResult)(function As System.Func(Of TResult)) As System.Threading.Tasks.Task(Of TResult)': Data type(s) of the type parameter(s) cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error.
'Public Function StartNew(action As System.Action) As System.Threading.Tasks.Task': Type 'IConnectionManager' is not defined.
'Public Function StartNew(action As System.Action) As System.Threading.Tasks.Task': 'Thread' is not declared. It may be inaccessible due to its protection level.
can you help me? thanks
HI dwarfVampire,
Deleteyou have some problems with your IConnectionManager and Threading
IConnectionManager is in Microsoft.AspNet.SignalR.Infrastructure library
The correct RouteTable is:
RouteTable.Routes.MapConnection(Of NotificationConnection)("NotificationConnection", "/NotificationConnection")
then, there is an arror in my connectionManager declaration, the right one is:
Dim connectonManager As IConnectionManager = GlobalHost.DependencyResolver.Resolve(Of IConnectionManager)()
Dim connection = connectonManager.GetConnectionContext(Of NotificationConnection)()
don't forget to import in your Global_asax class:
Imports System.Web.Routing
Imports System.Threading
Imports System.Threading.Tasks
Imports System
Imports System.Web
Imports Microsoft.AspNet.SignalR
Imports Microsoft.AspNet.SignalR.Infrastructure
Imports System.Collections.Generic
Imports System.Linq
Imports System.Diagnostics
Imports Microsoft.AspNet.SignalR.Hosting
let me know if it works.
bye
I am using VS 2013 and SignalR 2.0. Where I am running into errors is at the line:
ReplyDeleteRouteTable.Routes.MapConnection(Of NotificationConnection("NotificationConnection","/NotificationConnection"). The line is not compiling.
To be honest, I'm not completely sure what this line of code does (obviously mapping to the NotificationConnection class, but not sure why it is set up this way. Any help would be greatly appreciated.
Hi Hugh,
Deletethere is an error in step 4, a ")" is missing !!!.
Wrong:
RouteTable.Routes.MapConnection(Of NotificationConnection("NotificationConnection","/NotificationConnection")
Correct:
RouteTable.Routes.MapConnection(Of NotificationConnection)("NotificationConnection", "/NotificationConnection")
also in ConnectionManager declaration a ")" is missing
DeleteDim connectonManager As IConnectionManager = GlobalHost.DependencyResolver.Resolve(Of IConnectionManager)()
Thanks for the response, but I am receiving the error mapconnection is not a member of System.Web.Routing.RouteCollection. I have imported:
ReplyDeleteImports System.Web.SessionState
Imports System.Web.Routing
Imports System.Threading
Imports System.Threading.Tasks
Imports System
Imports System.Web
Imports Microsoft.AspNet.SignalR
Imports Microsoft.AspNet.SignalR.Infrastructure
Imports System.Collections.Generic
Imports System.Linq
Imports System.Diagnostics
Imports Microsoft.AspNet.SignalR.Hosting
Thanks again.
Hi Hugh,
Deletethe post is old so it's using an old version of signalR, but don't worry :-)
To use the new version:
1.let lose the global.asax file (comments all rows)
2.add a new class and paste this code:
Imports Owin
Imports Microsoft.AspNet.SignalR
Imports Microsoft.AspNet.SignalR.Infrastructure
Imports System.Threading
Imports System.Threading.Tasks
Public Class Startup
Public Sub Configuration(app As IAppBuilder)
app.MapSignalR(Of NotificationConnection)("/NotificationConnection")
Task.Factory.StartNew(Function()
Dim connectonManager As IConnectionManager = GlobalHost.DependencyResolver.Resolve(Of IConnectionManager)()
Dim connection = connectonManager.GetConnectionContext(Of NotificationConnection)()
While True
Dim item = New Notification() With { _
.Data = DateTime.Now.ToString("hh:mm:ss"), _
.ExamValue = CInt(Math.Ceiling(Rnd() * 100))
}
connection.Connection.Broadcast(item)
Thread.Sleep(1000)
End While
End Function)
End Sub
End Class
3. Replace the line in the html page
scripts/jquery.signalR-1.1.1.js
with new version
scripts/jquery.signalR-2.0.0.min.js"
I tested it and it is ok, I will appreciate if you let me know if everything is ok now
Giuseppe,
ReplyDeleteFirst of all, thanks for the help and thank you for providing the most straightforward, sensible example of a SignalR push that I have found. The changes worked perfectly and the project works as it should. To take things a step further, assuming you wanted to create a database push, would you create a SQLDependency in place of the While loop?