Introduction

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 make server code push the content to connected clients instantly as it becomes available, rather than having the server wait for a client to request the new data.

To Know more about SignalR, you can visit my blogs and articles.
Description

SignalR can be used to add any sort of "real-time" web functionality to your MVC 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. We must have a way to notify all the connected clients if there are any changes on the server, without a refresh or update the web page. This is the scenario in which ASP.NET SignalR comes handy.

Here, I have created two Views - for home and for Notification entry details. After that, the notifiation message will come with counting the no. of notifications arrived.
Link to download my project
Click Here>>
Steps to be followed

Step 1

Create one MVC application named "SignalRDemo".

Step 2


Create a table named "tblEmployee". Paste the following code in that.
  1. SET ANSI_NULLS ON
  2. GO
  3. SET QUOTED_IDENTIFIER ON
  4. GO
  5. SET ANSI_PADDING ON
  6. GO
  7. CREATE TABLE [dbo].[tblEmployee](
  8. [ID] [int] IDENTITY(1,1) NOT NULL,
  9. [Name] [varchar](50) NULL,
  10. [AddedOn] [datetime] NULL,
  11. PRIMARY KEY CLUSTERED
  12. (
  13. [ID] ASC
  14. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
  15. ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  16. ) ON [PRIMARY]
  17. GO
  18. SET ANSI_PADDING OFF
  19. GO
Step 3

Enable Service Broker on the database.
  1. ALTER DATABASE Your_DB_Name SET ENABLE_BROKER WITH ROLLBACK IMMEDIATE ;
Enable Service Broker on the database

Service Broker is a feature introduced for the first time in SQL Server 2005. By using this feature, external or internal processes can send and receive asynchronous messages reliably by using extensions of Transact-SQL Data Manipulation Language (DML). It is a queued and reliable messaging mechanism used for asynchronous programming model.We need this feature to be enabled since, whenever a change in the table will happen such as Insert/Update/Delete/Truncate, then the SQLDependency should be able to identify that.
It (Service Broker) rather implements a Broker Architecture which publishes the events while the SQL Dependency acts as a subscriber and detects the changes. Using the SqlDependency object, the application can create and register to receive notifications via the OnChangeEventHandler event handler.

How To Check Service Broker on the database Is Enabled Or Not?
  1. SELECT NAME, IS_BROKER_ENABLED FROM SYS.DATABASES
  2. WHERE NAME='Your_db_name'
Here I ennabled so IS_BROKER_ENABLED column shows "1" , else will show "0".

Step4

Add Ado.Net Entity Data Model named "SignalRDataModel.edmx".

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.

Step5

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" and Type below command .
  1. PM> Install-Package Microsoft.AspNet.SignalR
Step6

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"

Code Ref
  1. using Microsoft.Owin;
  2. using Owin;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Web;
  7. [assembly: OwinStartup(typeof(SignalRDemo.Startup))]
  8. namespace SignalRDemo
  9. {
  10. public class Startup
  11. {
  12. public void Configuration(IAppBuilder app)
  13. {
  14. app.MapSignalR();
  15. }
  16. }
  17. }
Step7

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".

Code Ref
  1. using Microsoft.AspNet.SignalR;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Web;
  6. namespace SignalRDemo
  7. {
  8. public class NotificationHub : Hub
  9. {
  10. //Nothing required here
  11. //public void Hello()
  12. //{
  13. // Clients.All.hello();
  14. //}
  15. }
  16. }
The NotificationHub.cs class is empty. I will use the class later from another place.
Step8

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.

Code Ref
  1. <add name="sqlConString" connectionString="Your_Connection_String" />
Step9

Add another class file named "NotificationComponent.cs" 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
Code Ref
  1. using Microsoft.AspNet.SignalR;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Configuration;
  5. using System.Data.SqlClient;
  6. using System.Linq;
  7. using System.Web;
  8. namespace SignalRDemo
  9. {
  10. public class NotificationComponent
  11. {
  12. //Here we will add a function for register notification (will add sql dependency)
  13. public void RegisterNotification(DateTime currentTime)
  14. {
  15. string conStr = ConfigurationManager.ConnectionStrings["sqlConString"].ConnectionString;
  16. string sqlCommand = @"SELECT [ID],[Name] from [dbo].[tblEmployee] where [AddedOn] > @AddedOn";
  17. //you can notice here I have added table name like this [dbo].[Contacts] with [dbo], its mendatory when you use Sql Dependency
  18. using (SqlConnection con = new SqlConnection(conStr))
  19. {
  20. SqlCommand cmd = new SqlCommand(sqlCommand, con);
  21. cmd.Parameters.AddWithValue("@AddedOn", currentTime);
  22. if (con.State != System.Data.ConnectionState.Open)
  23. {
  24. con.Open();
  25. }
  26. cmd.Notification = null;
  27. SqlDependency sqlDep = new SqlDependency(cmd);
  28. sqlDep.OnChange += sqlDep_OnChange;
  29. //we must have to execute the command here
  30. using (SqlDataReader reader = cmd.ExecuteReader())
  31. {
  32. // nothing need to add here now
  33. }
  34. }
  35. }
  36. void sqlDep_OnChange(object sender, SqlNotificationEventArgs e)
  37. {
  38. //or you can also check => if (e.Info == SqlNotificationInfo.Insert) , if you want notification only for inserted record
  39. if (e.Type == SqlNotificationType.Change)
  40. {
  41. SqlDependency sqlDep = sender as SqlDependency;
  42. sqlDep.OnChange -= sqlDep_OnChange;
  43. //from here we will send notification message to client
  44. var notificationHub = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
  45. notificationHub.Clients.All.notify("added");
  46. //re-register notification
  47. RegisterNotification(DateTime.Now);
  48. }
  49. }
  50. public List<tblEmployee> GetData(DateTime afterDate)
  51. {
  52. using (SignalRDBEntities dc = new SignalRDBEntities())
  53. {
  54. return dc.tblEmployees.Where(a => a.AddedOn > afterDate).OrderByDescending(a => a.AddedOn).ToList();
  55. }
  56. }
  57. }
  58. }
Code Description
The details code is explained using comment lines.
Step10

Add a new Controller named "HomeController.cs". Here I have added "Index" Action into "Home" Controller.

Code Ref
  1. public ActionResult Index()
  2. {
  3. return View();
  4. }
Step11
Then create one view for home controller.
Code Ref
  1. @{
  2. ViewBag.Title = "Home";
  3. }
  4. <h2>Index</h2>
  5. <a target="_blank" href="Add/">Go To Notification page>></a>
Code Description

This View is only for home page.
Step12

Add another action in HomeController to fetch Employee data.
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using System.Web.Mvc;
  6. namespace SignalRDemo.Controllers
  7. {
  8. public class HomeController : Controller
  9. {
  10. //
  11. // GET: /Home/
  12. public ActionResult Index()
  13. {
  14. return View();
  15. }
  16. public JsonResult GetNotifications()
  17. {
  18. var notificationRegisterTime = Session["LastUpdated"] != null ? Convert.ToDateTime(Session["LastUpdated"]) : DateTime.Now;
  19. NotificationComponent NC = new NotificationComponent();
  20. var list = NC.GetData(notificationRegisterTime);
  21. //update session here for get only new added contacts (notification)
  22. Session["LastUpdate"] = DateTime.Now;
  23. return new JsonResult { Data = list, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
  24. }
  25. }
  26. }
Code Description

The details code is explained using comment lines.
Step13

Add and update _Layout.cshtml for showing notification.

Code Ref
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>@ViewBag.Title - Satyaprakash Jquery and SignalR Intro</title>
  7. <link href="~/Content/bootstrap.css" rel="stylesheet" />
  8. <script src="~/Scripts/modernizr-2.6.2.js"></script>
  9. </head>
  10. <body>
  11. <div class="navbar navbar-inverse navbar-fixed-top">
  12. <div class="container">
  13. <div class="navbar-header">
  14. <span class="noti glyphicon glyphicon-globe"><span class="count"> </span></span>
  15. <div class="noti-content">
  16. <div class="noti-top-arrow"></div>
  17. <ul id="notiContent"></ul>
  18. </div>
  19. @Html.ActionLink("Satyaprakash Jquery and SignalR", "Index", "Home", null, new { @class = "navbar-brand" })
  20. </div>
  21. </div>
  22. </div>
  23. <div class="container body-content">
  24. @RenderBody()
  25. <hr />
  26. </div>
  27. @* Add Jquery Library *@
  28. <script src="~/Scripts/jquery-2.2.3.min.js"></script>
  29. <script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
  30. <script src="/signalr/hubs"></script>
  31. <script src="~/Scripts/bootstrap.min.js"></script>
  32. @* Add css *@
  33. <link href="~/Content/bootstrap.css" rel="stylesheet" />
  34. <style type="text/css">
  35. /*Added css for design notification area, you can design by your self*/
  36. /* COPY css content from youtube video description*/
  37. .noti-content{
  38. position:fixed;
  39. right:100px;
  40. background:yellow;
  41. color:blue;
  42. font-size:medium;
  43. font-style:oblique;
  44. font-family:Arial;
  45. border-radius:4px;
  46. top:47px;
  47. width:440px;
  48. display:none;
  49. border: 1px solid #9E988B;
  50. }
  51. ul#notiContent{
  52. max-height:200px;
  53. overflow:auto;
  54. padding:0px;
  55. margin:0px;
  56. padding-left:20px;
  57. }
  58. ul#notiContent li {
  59. margin: 3px;
  60. padding: 6px;
  61. background: #FF6600;
  62. }
  63. .noti-top-arrow{
  64. border-color:transparent;
  65. border-bottom-color:#F5DEB3;
  66. border-style:dashed dashed solid;
  67. border-width: 0 8.5px 8.5px;
  68. position:absolute;
  69. right:32px;
  70. top:-8px;
  71. }
  72. span.noti {
  73. color:lightgreen;
  74. margin: 15px;
  75. position: fixed;
  76. right: 100px;
  77. font-size: 30px;
  78. cursor: pointer;
  79. }
  80. span.count {
  81. position:fixed;
  82. top: -1px;
  83. /*color:white;*/
  84. }
  85. /*.noti:hover {
  86. color:white;
  87. }*/
  88. </style>
  89. @* Add jquery code for Get Notification & setup signalr *@
  90. <script type="text/javascript">
  91. $(function () {
  92. // Click on notification icon for show notification
  93. $('span.noti').click(function (e) {
  94. debugger;
  95. e.stopPropagation();
  96. $('span.noti').css("color", "lightgreen");
  97. $('span.count').hide();
  98. $('.noti-content').show();
  99. var count = 0;
  100. count = parseInt($('span.count').html()) || 0;
  101. count++;
  102. // only load notification if not already loaded
  103. if (count > 0) {
  104. updateNotification();
  105. }
  106. $('span.count', this).html(' ');
  107. })
  108. // hide notifications
  109. $('html').click(function () {
  110. $('.noti-content').hide();
  111. })
  112. // update notification
  113. function updateNotification() {
  114. $('#notiContent').empty();
  115. $('#notiContent').append($('<li>Loading...</li>'));
  116. $.ajax({
  117. type: 'GET',
  118. url: '/home/GetNotifications',
  119. success: function (response) {
  120. debugger;
  121. $('#notiContent').empty();
  122. if (response.length == 0) {
  123. $('#notiContent').append($('<li>Currently You Have No New Notifications.</li>'));
  124. }
  125. $.each(response, function (index, value) {
  126. $('#notiContent').append($('<li>The User , ' + value.Name+' ' +'Of ID' + ' (' + value.ID + ') Is Written
  127. Something.</li>'));
  128. });
  129. },
  130. error: function (error) {
  131. console.log(error);
  132. }
  133. })
  134. }
  135. // update notification count
  136. function updateNotificationCount() {
  137. $('span.count').show();
  138. var count = 0;
  139. count = parseInt($('span.count').html()) || 0;
  140. count++;
  141. $('span.noti').css("color", "white");
  142. $('span.count').css({ "background-color": "red", "color": "white" });
  143. $('span.count').html(count);
  144. }
  145. // signalr js code for start hub and send receive notification
  146. var notificationHub = $.connection.notificationHub;
  147. $.connection.hub.start().done(function () {
  148. console.log('Notification hub started');
  149. });
  150. //signalr method for push server message to client
  151. notificationHub.client.notify = function (message) {
  152. if (message && message.toLowerCase() == "added") {
  153. updateNotificationCount();
  154. }
  155. }
  156. })
  157. </script>
  158. </body>
  159. </html>
Code Description

The details code is explained using comment lines.

Step14

Update global.asax.cs to start, stop SQL dependency

Code Ref
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Configuration;
  4. using System.Data.SqlClient;
  5. using System.Linq;
  6. using System.Web;
  7. using System.Web.Http;
  8. using System.Web.Mvc;
  9. using System.Web.Routing;
  10. namespace SignalRDemo
  11. {
  12. // Note: For instructions on enabling IIS6 or IIS7 classic mode,
  13. // visit http://go.microsoft.com/?LinkId=9394801
  14. public class MvcApplication : System.Web.HttpApplication
  15. {
  16. string con = ConfigurationManager.ConnectionStrings["sqlConString"].ConnectionString;
  17. protected void Application_Start()
  18. {
  19. AreaRegistration.RegisterAllAreas();
  20. // WebApiConfig.Register(GlobalConfiguration.Configuration);
  21. // FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
  22. RouteConfig.RegisterRoutes(RouteTable.Routes);
  23. //here in Application Start we will start Sql Dependency
  24. SqlDependency.Start(con);
  25. }
  26. protected void Session_Start(object sender, EventArgs e)
  27. {
  28. NotificationComponent NC = new NotificationComponent();
  29. var currentTime = DateTime.Now;
  30. HttpContext.Current.Session["LastUpdated"] = currentTime;
  31. NC.RegisterNotification(currentTime);
  32. }
  33. protected void Application_End()
  34. {
  35. //here we will stop Sql Dependency
  36. SqlDependency.Stop(con);
  37. }
  38. }
  39. }
Code Description

The details code is explained using comment lines.

Step15

Now add a new Controller/Action To add Notification Data.
  1. I have created AddController.cs in Controller directory.
  2. Add action named "Index"
Code Ref:
  1. public ActionResult Index()
  2. {
  3. return View();
  4. }
Step16

Create View for Index action to add Employee Notification Details.

Code Ref
  1. @model SignalRDemo.tblEmployee
  2. @{
  3. ViewBag.Title = "Add Notification";
  4. }
  5. <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
  6. <link href="~/App_Content/CSS/bootstrap.min.css" rel="stylesheet" />
  7. <link href="~/App_Content/CSS/font-awesome.min.css" rel="stylesheet" />
  8. <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  9. <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  10. <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  11. <script src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js">
  12. </script>
  13. <style>
  14. .button {
  15. background-color: #4CAF50;
  16. border: none;
  17. color: white;
  18. padding: 15px 32px;
  19. text-align: center;
  20. text-decoration: none;
  21. display: inline-block;
  22. font-size: 16px;
  23. margin: 4px 2px;
  24. cursor: pointer;
  25. }
  26. .button4 {
  27. border-radius: 9px;
  28. }
  29. .control{
  30. width:459px;
  31. height:145px;
  32. }
  33. </style>
  34. <h2>Notification</h2>
  35. @using (Html.BeginForm(FormMethod.Post))
  36. {
  37. @Html.ValidationSummary(true)
  38. <fieldset>
  39. <legend>Notification</legend>
  40. <div class="editor-label">
  41. @Html.LabelFor(model => model.Name)
  42. </div>
  43. <div class="editor-field">
  44. @Html.TextAreaFor(model => model.Name, new { id = "ValidateNametextbox", @class = "form-control" })
  45. @Html.ValidationMessageFor(model => model.Name)
  46. </div>
  47. <p>
  48. <input id="SubmitProject" class="button button4" type="submit" value="Notify" onclick="saveToFile()" />
  49. </p>
  50. </fieldset>
  51. }
  52. <script type="text/javascript">
  53. function saveToFile() {
  54. if ($("#ValidateNametextbox").val() == "") {
  55. alert("Comment Section should not be empty!!");
  56. }
  57. else {
  58. alert("Go To Home Page of Client Browser.");
  59. }
  60. };
  61. </script>
Code Description

Here I have added some mvc controls like textarea and button.
  1. @using (Html.BeginForm(FormMethod.Post))
  2. {
  3. @Html.ValidationSummary(true)
  4. <fieldset>
  5. <legend>Notification</legend>
  6. <div class="editor-label">
  7. @Html.LabelFor(model => model.Name)
  8. </div>
  9. <div class="editor-field">
  10. @Html.TextAreaFor(model => model.Name, new { id = "ValidateNametextbox", @class = "form-control" })
  11. @Html.ValidationMessageFor(model => model.Name)
  12. </div>
  13. <p>
  14. <input id="SubmitProject" class="button button4" type="submit" value="Notify" onclick="saveToFile()" />
  15. </p>
  16. </fieldset>
  17. }
Step17

Add Post action for Index and add code to insert Employee.

Code Ref
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using System.Web.Mvc;
  6. namespace SignalRDemo.Controllers
  7. {
  8. public class AddController : Controller
  9. {
  10. //
  11. // GET: /Add/
  12. public ActionResult Index()
  13. {
  14. return View();
  15. }
  16. [HttpPost]
  17. public ActionResult Index(tblEmployee model)
  18. {
  19. SignalRDBEntities entity = new SignalRDBEntities();
  20. model.AddedOn = DateTime.Now;
  21. entity.tblEmployees.Add(model);
  22. entity.SaveChanges();
  23. return View();
  24. }
  25. }
  26. }
Code Description

Here I have added entityname "SignalRDBEntities" and using autogenerated class tblEmployee object model we added data on datetime when you insert data and for entity class object we inserted data on remaining table columns.
  1. SignalRDBEntities entity = new SignalRDBEntities();
The below two line has the main role to insert records.
  1. entity.tblEmployees.Add(model);
  2. entity.SaveChanges();
Step18

Here I configured my text area heading with "Add Comments." So, we should do an auto-generated class "tblEmployee.cs".

Code Ref
  1. //------------------------------------------------------------------------------
  2. // <auto-generated>
  3. // This code was generated from a template.
  4. //
  5. // Manual changes to this file may cause unexpected behavior in your application.
  6. // Manual changes to this file will be overwritten if the code is regenerated.
  7. // </auto-generated>
  8. //------------------------------------------------------------------------------
  9. namespace SignalRDemo
  10. {
  11. using System;
  12. using System.Collections.Generic;
  13. using System.ComponentModel.DataAnnotations;
  14. public partial class tblEmployee
  15. {
  16. public int ID { get; set; }
  17. [Display(Name = "Add Comments")]
  18. public string Name { get; set; }
  19. public Nullable<System.DateTime> AddedOn { get; set; }
  20. }
  21. }
Code Description

I added Display attribute to configure. So, you should add the namespace.
  1. using System.ComponentModel.DataAnnotations;

  2. [Display(Name = "Add Comments")]
  3. public string Name { get; set; }
Note

Sometimes due to more temporary and cache files the count will be a bit off. So, You should clean the solution and clean the project then Run....
OUTPUT

Home Page,



Then Notification insert page,



Add some notification text In Notification insert page



Then, it will show u a popup to go to home page to see the notification count as well as notification text.




You can see when there is no new notifiation, then the notification color is light green but when any new notification comes, the notification color is changed to white. Then, after clicking on the notification, the details will be shown and notification color is changed to light green. You can see some features are the same as Facebook Notification.




You can insert the data via one browser and get the updated notification on the homepage in the other browser also. The result will be shown in the same instance and different instance of same browser or different browser.

You can check the data inserted in the table.



In GIF -