This article particularly focus on a situation where multiple connected clients can perform the real time action for data insertion/updation/deletion and fetching by using MVC4, Entity Framework (Code First Approach) and SignalR.
Introduction
SignalR is the technology by which we can add real time web functionality to applications. That means, the server pushes the content/data to the connected clients instantaneously without the server waiting for the client for making a new data request.
Entity Framework (EF) is an Object Relational Mapper (ORM) that helps to work with relational data using domain-specific objects. For accessing the data, we will use the Code First Approach of EF.
ASP.NET MVC is a framework for building scalable, standards-based web applications.
This article particularly focus on a situation where multiple connected clients can perform the real time action for data insertion/updation/deletion and fetching by using MVC4, Entity Framework (Code First Approach) and SignalR.
N.B.~ Please read CRUD using Code First Approach of Entity Framework (EF) if you are new to Entity Framework (Code First Approach).
Straight to Experiment - Step by Step
Step 1 : Create MVC Project and add EF references
Let us fire Visual Studio 2015 and create a Web project (MVC project) first. Once done, then let's issue the following command from the Package Manager Console to install Entity Framework
Install-Package EntityFramework
Step 2 :Employee Model creation inside the Models Folder
Let us create an Employee entity class as under
using System.ComponentModel.DataAnnotations;
namespace WebApplication1.Models
{
public class Employee
{
[Key]
public int EmployeeID { get; set; }
public string EmployeeName { get; set; }
public string EmailAdress { get; set; }
public string MobileNumber { get; set; }
}
}
Step 3 :Create the Data Context class
Next create the EmployeeContext class as under
using System.Data.Entity;
using WebApplication1.Models;
namespace WebApplication1
{
public class EmployeeContext : DbContext
{
public EmployeeContext() : base("dbConnectionString")
{
Database.SetInitializer<EmployeeContext>(new CreateDatabaseIfNotExists<EmployeeContext>());
}
public DbSet<Employee> Employees { get; set; }
}
}
Step 4 :Add Connection String in Web.config
The next thing is to set up the connection string in web.config
<connectionStrings>
<add name="dbConnectionString" connectionString="Data Source=yourdatasource;Initial Catalog=EmployeeDB;User ID=youdbuserid;Password=yourdbpassword;pooling=false; MultipleActiveResultSets=True;pooling=false;" providerName="System.Data.SqlClient" />
</connectionStrings>
Step 5 :Install SignalR using Nuget
Next we will install SignalR by issuing the below command from the Package Manager Console
Install-Package Microsoft.AspNet.SignalR
Next we need to create Startup.cs file. The purpose of this file is to add a simple piece of middleware to the OWIN pipeline. For this to happen, let us right click on the WebApp project ->Add -> OWIN Startup class

Provide a class name say Startup

And the below will appear

We find the Startup class is decorated with
[assembly: OwinStartup(typeof(WebApp.Startup))]
This indicates that the class is implemented as a function that receives a Microsoft.Owin.IOwinContext instance. When the server receives an HTTP request, the OWIN pipeline invokes the middleware. The middleware sets the content type for the response and writes the response body.
Now, inside the Configuration function, we need to map SignalR hubs to the app builder pipeline at "/signalr". This can be done using the below way
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(WebApplication1.Startup))]
namespace WebApplication1
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
Next we need to create a Hub. A Hub is a class used for the communication for perstistent connections between client and server (hub). It makes Remote Procedure Calls (RPCs) from server to connected clients and from clients to the server. For this let us create a EmployeeHub.cs file and write the below code
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
namespace WebApplication1
{
public class EmployeeHub : Hub
{
[HubMethodName("NotifyClients")]
public static void NotifyCurrentEmployeeInformationToAllClients()
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<EmployeeHub>();
// the update client method will update the connected client about any recent changes in the server data
context.Clients.All.updatedClients();
}
}
}
Hub is an abstract class that provides methods that communicate with SignalR connections that is connected to Microsoft.AspNet.SignalR.Hub. The
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<EmployeeHub>();
gets the EmployeeHub context. The method updatedClients will the update client method will update the connected client about any recent changes in the server data.
context.Clients.All.updatedClients();
It calls the SignalR client part and informs it to execute the JavaScript method updatedClients(). The importance of Hub lies in sending different kinds of messages and data between client and server.
.
Step 6 :Create the Controller
Next we need to create the Controller as under
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web.Mvc;
using WebApplication1.Models;
namespace WebApplication1.Controllers
{
public class HomeController : Controller
{
List<Employee> empList;
//Fetch Employee Records
public ActionResult Index()
{
return View();
}
[HttpGet]
public ActionResult GetAllEmployeeRecords()
{
using (var context = new EmployeeContext())
{
empList = context
.Employees
.ToList();
}
return PartialView("_EmployeeList", empList);
}
//Insert Employee Record
public ActionResult Insert()
{
return View();
}
[HttpPost]
public ActionResult Insert(Employee employee)
{
if (ModelState.IsValid)
{
//Insert into Employee table
using (var context = new EmployeeContext())
{
context.Employees.Add(employee);
context.SaveChanges();
}
}
//Once the record is inserted , then notify all the subscribers (Clients)
EmployeeHub.NotifyCurrentEmployeeInformationToAllClients();
return RedirectToAction("Index");
}
//Update Employee Record
public ActionResult Update()
{
return View();
}
[HttpPost]
public ActionResult Update(Employee employee)
{
using (var context = new EmployeeContext())
{
var empRecord = context.Employees.Find(employee.EmployeeID);
empRecord.EmployeeName = employee.EmployeeName;
empRecord.EmailAdress = employee.EmailAdress;
empRecord.MobileNumber = employee.MobileNumber;
context.Employees.Add(empRecord);
context.Entry(empRecord).State = EntityState.Modified;
context.SaveChanges();
}
//Once the record is inserted , then notify all the subscribers (Clients)
EmployeeHub.NotifyCurrentEmployeeInformationToAllClients();
return RedirectToAction("Index");
}
//Delete Employee Record
[HttpPost]
public ActionResult Delete(Employee employee)
{
using (var context = new EmployeeContext())
{
var empRecord = context.Employees.Find(employee.EmployeeID);
context.Employees.Remove(empRecord);
context.SaveChanges();
}
//Once the record is inserted , then notify all the subscribers (Clients)
EmployeeHub.NotifyCurrentEmployeeInformationToAllClients();
return RedirectToAction("Index");
}
}
}
Step 7 :Shaping the View
Finally, it's turn to make the UI design and invoke the Controller API's and notify the clients about the instantaneous updates which SignalR will take care. Let us first code the Index.cshtml file as under
@model IList<WebApplication1.Models.Employee>
@{
ViewBag.Title = "Index";
}
<link href="~/Content/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<div>
<h1 style="color: green">CRUD using SignalR,MVC and Entity Framework</h1>
<table border="1">
<tr>
<td>
<h1 style="color:blueviolet">Add/Update/Delete Employee</h1>
<table border="1">
<tr>
<td>Employee Id</td>
<td><input id="txtEmployeeId" type="text" /></td>
</tr>
<tr>
<td>Employee Name</td>
<td><input id="txtEmployeeName" type="text" /></td>
</tr>
<tr>
<td>Email Address</td>
<td><input id="txtEmail" type="text" /></td>
</tr>
<tr>
<td>Mobile Number</td>
<td><input id="txtMobile" type="text" /></td>
</tr>
</table>
<table border="1">
<tr>
<td><button id="btnPostEmployee" onclick="InsertEmployee()">Add New Employee</button></td>
<td>
<button id="btnPutEmployee" onclick="UpdateEmployee()">Update Employee</button>
<button id="btnDeleteEmployee" onclick="DeleteEmployee();return false;">Delete Employee</button>
</td>
</tr>
</table>
</td>
</tr>
</table>
<br /><br />
<div id="dataTable"></div>
</div>
@section JavaScript{
<script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
<script src="/signalr/hubs"></script>
<script type="text/javascript">
$(function () {
// Create a proxy to signalr hub on web server. It reference the hub.
var notificationFromHub = $.connection.employeeHub;
// Connect to signalr hub
$.connection.hub.start().done(function () {
FetchEmployees();
});
// Notify to client with the recent updates
notificationFromHub.client.updatedClients = function () {
FetchEmployees();
};
});
function FetchEmployees() {
var model = $('#dataTable');
$.ajax({
url: '/home/GetAllEmployeeRecords',
contentType: 'application/html ; charset:utf-8',
type: 'GET',
dataType: 'html'
})
.success(function (result) { model.empty().append(result); })
}
// Insert Employee Record
function InsertEmployee()
{
var employee = {
EmployeeID: $('#txtEmployeeId').val(),
EmployeeName: $('#txtEmployeeName').val(),
EmailAdress: $('#txtEmail').val(),
MobileNumber: $('#txtMobile').val()
};
$.ajax({
url: '/home/Insert',
type: 'POST',
data: JSON.stringify(employee),
contentType: "application/json;charset=utf-8",
success: function (data) {
alert('Employee added Successfully');
},
error: function () {
alert('Employee not Added');
}
});
}
// Update Employee Record
function UpdateEmployee() {
var employee = {
EmployeeID: $('#txtEmployeeId').val(),
EmployeeName: $('#txtEmployeeName').val(),
EmailAdress: $('#txtEmail').val(),
MobileNumber: $('#txtMobile').val()
};
$.ajax({
url: '/home/Update',
type: 'POST',
data: JSON.stringify(employee),
contentType: "application/json;charset=utf-8",
success: function (data) {
alert('Employee updated Successfully');
},
error: function (e) {
alert('Employee could not be updated');
}
});
}
// Delete Employee Record
function DeleteEmployee() {
var employee = {
EmployeeID: $('#txtEmployeeId').val()
};
$.ajax({
url: '/home/Delete',
type: 'POST',
data: JSON.stringify(employee),
contentType: "application/json;charset=utf-8",
success: function (data) {
alert('Employee deleted Successfully');
},
error: function (x, y, z) {
alert(x + '\n' + y + '\n' + z);
}
});
}
</script>
}
The code snippet
$(function () {
// Create a proxy to signalr hub on web server. It reference the hub.
var notificationFromHub = $.connection.employeeHub;
// Connect to signalr hub
$.connection.hub.start().done(function () {
FetchEmployees();
});
// Notify to client with the recent updates
notificationFromHub.client.updatedClients = function () {
FetchEmployees();
};
});
indicates that, first we are creating a proxy to SignalR Hub on web server. Once done, then we need to establish a connection to the Hub. The server will notify the clients with the recent updates of the records through the updatedClients method.
Next create a partial view _EmployeeList.cshtml that will be use for displaying the Employee Records.
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>EmployeeID</th>
<th>EmployeeName</th>
<th>Email ID</th>
<th>PhoneNumber</th>
</tr>
</thead>
<tbody>
@if (Model != null)
{
foreach (var item in Model)
{
<tr>
<td>@item.EmployeeID</td>
<td>@item.EmployeeName</td>
<td>@item.EmailAdress</td>
<td>@item.MobileNumber</td>
</tr>
}
}
</tbody>
</table>
The entire project structure looks as under

Step 8 :Run the Application
Let us open the Application in two different browsers say one in Chrome and the other in FireFox.
The landing page looks as under

Let us Insert an Employee Record from Chrome Browser and see the reflection in FireFox

We can figure out that an instantaneous update has happen without delay in waiting time and no flickering. The same happens for other operations.
N.B.~ If we are changing the Model once the DB tables has been created, then we need to
1. Enable-Migrations first,
2. then add-migration
3. followed by update-database commands from package manager console.

Reference
- Tutorial: Getting Started with SignalR 2
- Introduction to SignalR
- CRUD using Code First Approach of Entity Framework (EF)
Conclusion
Hope this will be helpful to understand the "real time" notification by using SignalR. Thanks for reading. Zipped file attached.