ASP.NET SignalR is a library for ASP.NET developers that simplifies the process of adding real-time web functionality to applications. Real-time web functionality is the ability to have server code push content to connected clients instantly as it becomes available, rather than having the server wait for a client to request new data.
SignalR can be used to add any sort of "real-time" web functionality to your ASP.NET application. While chat is often used as an example, you can do a whole lot more. Examples include dashboards and monitoring applications, collaborative applications (such as simultaneous editing of documents), job progress updates, and real-time forms.
Now a days, Most of the web applications are multiuser application, where multiple users connected at the same time. But the problem is when any user does any changes (ex. insert a new record) other users doesn’t know it unless the request is initiated by the user for seeking the any updates.
So, we must have a way to notify all the connected clients if there is any changes happens on the server without a refresh or update the web page. This is the scenario in which asp.net SignalR comes.
SignalR can be used to add any sort of "real-time" web functionality to your ASP.NET application. While chat is often used as an example, you can do a whole lot more. Examples include dashboards and monitoring applications, collaborative applications (such as simultaneous editing of documents), job progress updates, and real-time forms.
Now a days, Most of the web applications are multiuser application, where multiple users connected at the same time. But the problem is when any user does any changes (ex. insert a new record) other users doesn’t know it unless the request is initiated by the user for seeking the any updates.
So, we must have a way to notify all the connected clients if there is any changes happens on the server without a refresh or update the web page. This is the scenario in which asp.net SignalR comes.
Creating a push notification system with SignalR
Follow the below steps in order to implement "push notification system with SignalR in asp.net MVC".
Here In this Example, I am using Visual Studio 2012
Step-1: Create New Empty MVC Project.
Step-2: Add a SQL Server Database.
Create database SignalRDB;
Create table tblEmployee(
ID int
Identity,
Name varchar(50)
null
)
Step-3: Enable Service Broker on the database.
ALTER DATABASE SignalRDB SET
ENABLE_BROKER WITH
ROLLBACK IMMEDIATE
;
Step-4: Add Entity Data Model.
Go to Solution Explorer (Visual studio) > Right Click on Project name form Solution Explorer > Add > New item > Select ADO.net Entity Data Model under data > Enter model name > Add.
A popup window will come (Entity Data Model Wizard) > Select Generate from database > Next >
Chose your data connection > select your database > next > Select tables > enter Model Namespace > Finish.
Step-5: Install SignalR NuGet Package.
Solution Explorer > Right Click on References > Manage NuGetPackages > Search for "SignalR"> Install > Close.
Or you can also install from package manager console.
Go to Tools (top menu) > Library Package Manager > Open "Package Manager Console"
Type below command
PM> Install-Package Microsoft.AspNet.SignalR
Step-6: Add an Owin startup file.
Add an Owin startup class in your application for enabling the SignalR in our application.
Add a new class in the project named "Startup.cs"
Write following code in Startup.cs file.
using Microsoft.Owin;
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
[assembly: OwinStartup(typeof(SignalRDemo.Startup))]
namespace SignalRDemo
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
Step-7: Add a SignalR hub class.
Now, you need to create a SignalR Hub class, this makes possible to invoke the client side JavaScript method from the server side. In this application, we will use this for showing notification.
SignalR uses ‘Hub’ objects to communicate between the client and the server.
Add a new class named "NotificationHub.cs"
Enter the following contents into the file.
using Microsoft.AspNet.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace SignalRDemo
{
public class NotificationHub : Hub
{
//Nothing required here
//public void Hello()
//{
// Clients.All.hello();
//}
}
}
you can see above, the NotificationHub.cs class is empty. Left the class empty as we will use the class later from another place.
Step-8: Add connection string into the web.config file
Open the application root Web.config file and find the element. Add the following connection string to the element in the Web.config file.
<add name="sqlConString" connectionString="data source=VL32-PC-SURAJ\SQLEXPRESS;initial catalog=SignalRDB;user id=sa;password=Test@123;" />
Step-9: Add another class file for register notification for data changes in the database
In this class, you need to create a SQL dependency which allows your application to be notified when a data has changed in the database (Microsoft SQL Server). Write the following in this class...
1. RegisterNotification- void method for register notification
2. SqlDependency_OnChange- SqlDependency onchnage event, get fired when assigned SQL command produced a different
3. GetContacts- This is a method for return the changes happened on the server, here our new inserted contact data
using Microsoft.AspNet.SignalR;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
namespace SignalRDemo
{
public class NotificationComponent
{
//Here we will add a function for register notification (will add sql dependency)
public void RegisterNotification(DateTime currentTime)
{
string conStr = ConfigurationManager.ConnectionStrings["sqlConString"].ConnectionString;
string sqlCommand = @"SELECT [ID],[Name] from [dbo].[tblEmployee] where [AddedOn] > @AddedOn";
//you can notice here I have added table name like this [dbo].[Contacts] with [dbo], its mendatory when you use Sql Dependency
using (SqlConnection con = new SqlConnection(conStr))
{
SqlCommand cmd = new SqlCommand(sqlCommand, con);
cmd.Parameters.AddWithValue("@AddedOn", currentTime);
if (con.State != System.Data.ConnectionState.Open)
{
con.Open();
}
cmd.Notification = null;
SqlDependency sqlDep = new SqlDependency(cmd);
sqlDep.OnChange += sqlDep_OnChange;
//we must have to execute the command here
using (SqlDataReader reader = cmd.ExecuteReader())
{
// nothing need to add here now
}
}
}
void sqlDep_OnChange(object sender, SqlNotificationEventArgs e)
{
//or you can also check => if (e.Info == SqlNotificationInfo.Insert) , if you want notification only for inserted record
if (e.Type == SqlNotificationType.Change)
{
SqlDependency sqlDep = sender as SqlDependency;
sqlDep.OnChange -= sqlDep_OnChange;
//from here we will send notification message to client
var notificationHub = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
notificationHub.Clients.All.notify("added");
//re-register notification
RegisterNotification(DateTime.Now);
}
}
public List<tblEmployee> GetData(DateTime afterDate)
{
using (SignalRDBEntities dc = new SignalRDBEntities())
{
return dc.tblEmployees.Where(a => a.AddedOn > afterDate).OrderByDescending(a => a.AddedOn).ToList();
}
}
}
}
Step-10: Create an MVC Controller
Add a new Controller named "HomeController.cs"
Step-11: Add new action into your controller.
Here I have added "Index" Action into "Home" Controller.
Step-13: Add another action in HomeController tofetch Employee data.
Step-15: Update global.asax.cs to start, stop SQL dependency
Step-16: Run Application.
Step-17: Now add a new Controller/Action To add Employee Data.
1- I have created AddController.cs in Controller directory.
2- Add action named "Index"
3- Create View for Index action to add Employee
4- Add Post action for Index and add code to insert Employee
Step-18: Run Application.
Click On Add Employee Link. it will open a new Page.
Click here to download this project Download
Like and share if you liked this post.
Add a new Controller named "HomeController.cs"
Step-11: Add new action into your controller.
Here I have added "Index" Action into "Home" Controller.
public ActionResult Index()
{
return View();
}
Step-12: Add view for your Action named "Index.cshtml"
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<a target="_blank" href="Add/">Add
Employe</a>
public JsonResult GetNotifications()
{
var notificationRegisterTime = Session["LastUpdated"] != null ? Convert.ToDateTime(Session["LastUpdated"]) : DateTime.Now;
NotificationComponent NC = new NotificationComponent();
var list = NC.GetData(notificationRegisterTime);
//update session here for get only new added contacts (notification)
Session["LastUpdate"] = DateTime.Now;
return new JsonResult { Data = list, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
Step-14: Add and update _Layout.cshtml for showing notification.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - MY SignalR Demo</title>
<link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
<script src="~/Scripts/modernizr-2.6.2.js"></script>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<span class="noti glyphicon glyphicon-bell"><span class="count"> </span></span>
<div class="noti-content">
<div class="noti-top-arrow"></div>
<ul id="notiContent"></ul>
</div>
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
@Html.ActionLink("SignalR Demo", "Index", "Home", null, new { @class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
</ul>
</div>
</div>
</div>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>© @DateTime.Now.Year - My SignalR Demo</p>
</footer>
</div>
@* Add Jquery Library *@
<script src="~/Scripts/jquery-2.2.3.min.js"></script>
<script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
<script src="/signalr/hubs"></script>
<script src="~/Scripts/bootstrap.min.js"></script>
@* Add css *@
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
<style type="text/css">
/*Added css for design notification area, you can design by your self*/
/* COPY css content from youtube video description*/
.noti-content{
position:fixed;
right:100px;
background:#e5e5e5;
border-radius:4px;
top:47px;
width:250px;
display:none;
border: 1px solid #9E988B;
}
ul#notiContent{
max-height:200px;
overflow:auto;
padding:0px;
margin:0px;
padding-left:20px;
}
ul#notiContent li {
margin:3px;
padding:6px;
background:#fff;
}
.noti-top-arrow{
border-color:transparent;
border-bottom-color:#F5DEB3;
border-style:dashed dashed solid;
border-width: 0 8.5px 8.5px;
position:absolute;
right:32px;
top:-8px;
}
span.noti{
color:#FF2323;
margin:15px;
position:fixed;
right:100px;
font-size:18px;
cursor:pointer;
}
span.count{
position:relative;
top:-3px;
}
</style>
@* Add jquery code for Get Notification & setup signalr *@
<script type="text/javascript">
$(function () {
// Click on notification icon for show notification
$('span.noti').click(function (e) {
debugger;
e.stopPropagation();
$('.noti-content').show();
var count = 0;
count = parseInt($('span.count').html()) || 0;
//only load notification if not already loaded
if (count > 0) {
updateNotification();
}
$('span.count', this).html(' ');
})
// hide notifications
$('html').click(function () {
$('.noti-content').hide();
})
// update notification
function updateNotification() {
$('#notiContent').empty();
$('#notiContent').append($('<li>Loading...</li>'));
$.ajax({
type: 'GET',
url: '/home/GetNotifications',
success: function (response) {
debugger;
$('#notiContent').empty();
if (response.length == 0) {
$('#notiContent').append($('<li>No data available</li>'));
}
$.each(response, function (index, value) {
$('#notiContent').append($('<li>New contact : ' + value.Name + ' (' + value.ID + ') added</li>'));
});
},
error: function (error) {
console.log(error);
}
})
}
// update notification count
function updateNotificationCount() {
var count = 0;
count = parseInt($('span.count').html()) || 0;
count++;
$('span.count').html(count);
}
// signalr js code for start hub and send receive notification
var notificationHub = $.connection.notificationHub;
$.connection.hub.start().done(function () {
console.log('Notification hub started');
});
//signalr method for push server message to client
notificationHub.client.notify = function (message) {
if (message && message.toLowerCase() == "added") {
updateNotificationCount();
}
}
})
</script>
</body>
</html>
Step-15: Update global.asax.cs to start, stop SQL dependency
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Routing;
namespace SignalRDemo
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
string con = ConfigurationManager.ConnectionStrings["sqlConString"].ConnectionString;
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
// WebApiConfig.Register(GlobalConfiguration.Configuration);
// FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
//here in Application Start we will start Sql Dependency
SqlDependency.Start(con);
}
protected void Session_Start(object sender, EventArgs e)
{
NotificationComponent NC = new NotificationComponent();
var currentTime = DateTime.Now;
HttpContext.Current.Session["LastUpdated"] = currentTime;
NC.RegisterNotification(currentTime);
}
protected void Application_End()
{
//here we will stop Sql Dependency
SqlDependency.Stop(con);
}
}
}
Step-16: Run Application.
Step-17: Now add a new Controller/Action To add Employee Data.
1- I have created AddController.cs in Controller directory.
2- Add action named "Index"
public ActionResult Index()
{
return View();
}
@model SignalRDemo.tblEmployee
@{
ViewBag.Title = "Index";
}
<h2>Add Employee</h2>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Add Employee</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
4- Add Post action for Index and add code to insert Employee
[HttpPost]
public ActionResult Index(tblEmployee model)
{
SignalRDBEntities entity = new SignalRDBEntities();
model.AddedOn = DateTime.Now;
entity.tblEmployees.Add(model);
entity.SaveChanges();
return View();
}
Step-18: Run Application.
Click On Add Employee Link. it will open a new Page.
Type Name in textbox and click on Create button.it saves data in the table. Now go to first tab to see notification.
Like and share if you liked this post.
Thanks-
Nice one. Keep it up
ReplyDeleteTHankyou Dilip
Deletei want to know why += and -= e.g sqlDep.OnChange -= sqlDep_OnChange;
ReplyDeleteUkm sumut
ReplyDeleteKosngosan
Virtual Office di Jakarta
Sibakua