In this post, we are going to explore how to implement user-based notification using ASP.NET MVC and SignalR. If you are new to SignalR, please get some basics here.
Why SignalR?
SignalR provides "real-time" web functionality in our application using Javascript function call in client browser from the server (Server-sent Events). It has several connections for management like
- connect/disconnect/reconnect events,
- grouping connections,
- authorization etc
Go to http://signalr.net for more.
We will focus on
- Creating a new ASP.Net MVC Web Application
- Add SignalR
- Creating Hub
- Enable SignalR
- Database Modification
- Send specific user Notification using SignalR
Create ASP.Net MVC Web Application
Open Visual Studio go to > File >New Project Choose ASP.Net MVC application.
![ASP.NET]()
Choose a template. In my case, I have used MVC. Check Web API reference then hit ok button, that’s it. Build & run the application for the first time.
Add SignalR
Get it on NuGet! Right click the project > Manage NuGet package > Browse to install.
![ASP.NET]()
Browse package then install to application, it’ll automatically do the rest.
![ASP.NET]()
OR Install using package manager console
Install-Package Microsoft.AspNet.SignalR.
![ASP.NET]()
Creating Hub
Add a new Hub Class
, name it NotificationHub.cs.
![ASP.NET]()
- public class NotificationHub : Hub
- {
- private static readonly ConcurrentDictionary<string, UserHubModels> Users =
- new ConcurrentDictionary<string, UserHubModels>(StringComparer.InvariantCultureIgnoreCase);
-
-
- public override Task OnConnected()
- {
- string userName = Context.User.Identity.Name;
- string connectionId = Context.ConnectionId;
-
- var user = Users.GetOrAdd(userName, _ => new UserHubModels
- {
- UserName = userName,
- ConnectionIds = new HashSet<string>()
- });
-
- lock (user.ConnectionIds)
- {
- user.ConnectionIds.Add(connectionId);
- if (user.ConnectionIds.Count == 1)
- {
- Clients.Others.userConnected(userName);
- }
- }
-
- return base.OnConnected();
- }
-
- public override Task OnDisconnected(bool stopCalled)
- {
- string userName = Context.User.Identity.Name;
- string connectionId = Context.ConnectionId;
-
- UserHubModels user;
- Users.TryGetValue(userName, out user);
-
- if (user != null)
- {
- lock (user.ConnectionIds)
- {
- user.ConnectionIds.RemoveWhere(cid => cid.Equals(connectionId));
- if (!user.ConnectionIds.Any())
- {
- UserHubModels removedUser;
- Users.TryRemove(userName, out removedUser);
- Clients.Others.userDisconnected(userName);
- }
- }
- }
-
- return base.OnDisconnected(stopCalled);
- }
- }
Enable SignalR - Startup.cs
- using Microsoft.Owin;
- using Owin;
-
- [assembly: OwinStartupAttribute(typeof(NotifSystem.Web.Startup))]
- namespace NotifSystem.Web
- {
- public partial class Startup
- {
- public void Configuration(IAppBuilder app)
- {
- app.MapSignalR();
- }
- }
- }
Layout page
- <script src="~/Scripts/jquery.signalR-2.2.2.min.js"></script>
- <script src="~/signalr/hubs"></script>
- <script type="text/javascript">
- $(document).ready(function () {
- var hub = $.connection.notificationHub;
- $.connection.hub.start()
- .done(function () {
- console.log("Hub Connected!");
-
- })
- .fail(function () {
- console.log("Could not Connect!");
- });
- });
- </script>
Test SignalR
Run the application go to url modify by /signalr/hubs. This will show the magic SignalR JavaScript Library with the current version like below screenshot.
![ASP.NET]()
In Browser Console it’ll show message about Hub Connection.
![ASP.NET]()
Database Modification
Create new database then modify connection string in web.config file. Restore database from attached script file in App_Data folder.
We need to create a table to store Notifications.
- CREATE TABLE [dbo].[Notification](
- [Id] [int] IDENTITY(1,1) NOT NULL,
- [Type] [int] NULL,
- [Details] [nvarchar](500) NULL,
- [Title] [nvarchar](50) NULL,
- [DetailsURL] [nvarchar](500) NULL,
- [SentTo] [nvarchar](50) NULL,
- [Date] [date] NULL,
- [IsRead] [bit] NULL,
- [IsDeleted] [bit] NULL,
- [IsReminder] [bit] NULL,
- [Code] [nvarchar](100) NULL,
- [NotificationType] [nvarchar](100) NULL,
- CONSTRAINT [PK_Notification] PRIMARY KEY CLUSTERED
- (
- [Id] ASC
- )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
- ) ON [PRIMARY]
- GO
Send specific user Notification using SignalR
In this section we will work with view to send notification to specific user.
Index.cshtml
- <div class="col-md-12">
- <h2>Say Hello</h2>
- <div id="messages"></div>
- <hr />
-
- <div class="form-group">
- <label for="email">User Email:</label>
- <input type="email" class="form-control" id="toUser" value="" placeholder="[email protected]"/>
- </div>
- <div class="form-group">
- <label for="pwd">Message:</label>
- <input type="password" class="form-control" id="myMessage" value="" placeholder="message"/>
- </div>
-
- <button type="submit" class="btn btn-default" id="submit">Submit</button>
-
- </div>
Javascript
- <script type="text/javascript">
- $("#submit").click(function (e) {
- e.preventDefault();
-
- var message = $("#myMessage").val();
- var sendtouser = $("#toUser").val();
-
- var Notification = { UserID: sendtouser, Message: message };
-
- $.ajax({
- type: "POST",
- url: "/api/Values/SendNotification",
- data: JSON.stringify(Notification),
- contentType: 'application/json; charset=utf-8',
- success: function (data) {
-
- $("#myMessage").val("");
- },
- error: function () {
- alert("Error occured!!")
- }
- });
-
- });
- </script>
API
- public class ValuesController : ApiController
- {
- private NotifEntities context = new NotifEntities();
-
- [HttpPost]
- public HttpResponseMessage SendNotification(NotifModels obj)
- {
- NotificationHub objNotifHub = new NotificationHub();
- Notification objNotif = new Notification();
- objNotif.SentTo = obj.UserID;
-
- context.Configuration.ProxyCreationEnabled = false;
- context.Notifications.Add(objNotif);
- context.SaveChanges();
-
- objNotifHub.SendNotification(objNotif.SentTo);
-
-
-
-
- return Request.CreateResponse(HttpStatusCode.OK);
- }
- }
Modify Hub
We need to add additional methods in our Hub class.
- private NotifEntities context = new NotifEntities();
-
-
- public void GetNotification()
- {
- try
- {
- string loggedUser = Context.User.Identity.Name;
-
-
- string totalNotif = LoadNotifData(loggedUser);
-
-
- UserHubModels receiver;
- if (Users.TryGetValue(loggedUser, out receiver))
- {
- var cid = receiver.ConnectionIds.FirstOrDefault();
- var context = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
- context.Clients.Client(cid).broadcaastNotif(totalNotif);
- }
- }
- catch (Exception ex)
- {
- ex.ToString();
- }
- }
-
-
- public void SendNotification(string SentTo)
- {
- try
- {
-
- string totalNotif = LoadNotifData(SentTo);
-
-
- UserHubModels receiver;
- if (Users.TryGetValue(SentTo, out receiver))
- {
- var cid = receiver.ConnectionIds.FirstOrDefault();
- var context = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
- context.Clients.Client(cid).broadcaastNotif(totalNotif);
- }
- }
- catch (Exception ex)
- {
- ex.ToString();
- }
- }
-
- private string LoadNotifData(string userId)
- {
- int total = 0;
- var query = (from t in context.Notifications
- where t.SentTo == userId
- select t)
- .ToList();
- total = query.Count;
- return total.ToString();
- }
Finally the Hub
Output
![ASP.NET]()
Hope this will help.