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.
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.
Browse package then install to application, it’ll automatically do the rest.
OR Install using package manager console
Install-Package Microsoft.AspNet.SignalR.
Creating Hub
Add a new Hub Class
, name it NotificationHub.cs.
- 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.
In Browser Console it’ll show message about Hub Connection.
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
Hope this will help.