Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create real time notification module like Facebook for database changes

I'm Trying to create notification module like Facebook using ASP.NET MVC 4.

I have few tables in my Database.

As soon as someone change (Insert/Update/Delete) row of those tables in database I'll be able to show it as notification in my application front end

Just want to know best way to figure this thing out , Highly appreciate can give any suggestion or resource

Thank You!

like image 325
kez Avatar asked Dec 25 '22 23:12

kez


1 Answers

You can use SignalR which is a library for developing applications needing real-time communication.In such applications as soon as data is generated on the server or some interesting event happens on the server the client needs to be updated with the latest data. The traditional approach to achieve this functionality is to make Ajax calls to the server periodically. However, this approach has its own pitfalls. Another way is to use HTML5 Web Sockets or Server Sent Events (SSE) to perform real-time communication. However, both of these techniques work only on the browsers supporting HTML5. SignalR uses HTML5 Web Sockets if the target browser supports them, otherwise it falls back to other techniques.

To create a notification system .If you are using ASP.NET WebForms add a new SignalR Hub Class to the project like this:

namespace SignalRDemo
{
    public class MyHub1 : Hub
    {
            //call method like SendNotifications when your database is changed
            public void SendNotifications(string message)
            {
                Clients.All.receiveNotification(message);
            }
    }
}

Next, add a Global.asax file to your web application and write the following code in the Application_Start event handler.

protected void Application_Start(object sender, EventArgs e)
{
    RouteTable.Routes.MapHubs();
}

Additionally, you will find certain script files under the Scripts folder.

SignalR Scripts

Now, add a web form to the project and name it as AdminForm.aspx. Add the following markup in the web form:

<!DOCTYPE html>
<html>
<head>
    <title>Admin Form Sending Notifications</title>

    <script src="/Scripts/jquery-1.8.2.min.js" ></script>
    <script src="/Scripts/jquery.signalR-1.0.0.js"></script>
    <script src="/signalr/hubs"></script>

    <script type="text/javascript">
        $(function () {
            var proxy = $.connection.notificationHub;
            $("#button1").click(function () {
                proxy.server.sendNotifications($("#text1").val());
            });
            $.connection.hub.start();
        });
    </script>

</head>
<body>
    <input id="text1" type="text" />
    <input id="button1" type="button" value="Send" />
</body>
</html>

The AdminForm.aspx refers SignalR script files in the head section. Notice the code marked in the bold letters. First a variable named proxy is declared to hold a reference to a proxy of the remote hub class (NotificationHub). Make sure that the client side code uses camel casing in naming conventions. For example, NotificationHub is referred as notificationHub in the client code.

Next, the click event handler of the button is wired to a function. The client event handler calls the sendNotifications() method on the proxy object and passes the notification message entered in the textbox (see earlier figure to know what the admin form looks like).

Finally, the start() method of the hub is called to start the connection.

Add another web form to the project and name it ClientForm.aspx. Key-in the following markup in the web form:

<!DOCTYPE html>
<html>
<head>
    <title>Client Form Receiving Notifications</title>
    <script src="/Scripts/jquery-1.8.2.min.js" ></script>
    <script src="/Scripts/jquery.signalR-1.0.0.js"></script>
    <script src="/signalr/hubs"></script>
    <script type="text/javascript">
        $(function () {
            var proxy = $.connection.notificationHub;
            proxy.client.receiveNotification = function (message) {
                $("#container").html(message);
                $("#container").slideDown(2000);
                setTimeout('$("#container").slideUp(2000);', 5000);
            };
            $.connection.hub.start();
        });
    </script>
</head>
<body>
    <div class="notificationBalloon" id="container">
    </div>
</body>
</html>

Now the notification send from the admin will be shown to all client like this.

To display real time updates from the SQL Server by using SignalR and SQL Dependency follow these steps:

Step 1: Enable Service Broker on the database

The following is the query that need to enable the service broker

ALTER DATABASE BlogDemos SET ENABLE_BROKER WITH ROLLBACK IMMEDIATE ;

Step 2: Enable SQL Dependency

    //Start SqlDependency with application initialization
     SqlDependency.Start(connString);

Step 3: Create the hub Class

public class MessagesHub : Hub
    {
        private static string conString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ToString();
        public void Hello()
        {
            Clients.All.hello();
        }

        [HubMethodName("sendMessages")]
        public static void SendMessages()
        {
            IHubContext context = GlobalHost.ConnectionManager.GetHubContext<MessagesHub>();
            context.Clients.All.updateMessages();
        }


    }

Step 4: Get the Data from the Repository

Create MessagesRepository to get the messages from the database when data is updated.

public class MessagesRepository
    {
        readonly string _connString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;

        public IEnumerable<Messages> GetAllMessages()
        {
            var messages = new List<Messages>();
            using (var connection = new SqlConnection(_connString))
            {
                connection.Open();
                using (var command = new SqlCommand(@"SELECT [MessageID], [Message], [EmptyMessage], [Date] FROM [dbo].[Messages]", connection))
                {
                    command.Notification = null;

                    var dependency = new SqlDependency(command);
                    dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);

                    if (connection.State == ConnectionState.Closed)
                        connection.Open();

                    var reader = command.ExecuteReader();

                    while (reader.Read())
                    {
                        messages.Add(item: new Messages { MessageID = (int)reader["MessageID"], Message = (string)reader["Message"], EmptyMessage =  reader["EmptyMessage"] != DBNull.Value ? (string) reader["EmptyMessage"] : "", MessageDate = Convert.ToDateTime(reader["Date"]) });
                    }
                }

            }
            return messages;


        }

        private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
        {
            if (e.Type == SqlNotificationType.Change)
            {
                MessagesHub.SendMessages();
            }
        }
    }

Step 5: Register SignalR at startup class

app.MapSignalR();

Step 6: then use the method to show real time at your view

<script src="/Scripts/jquery.signalR-2.1.1.js"></script>
 <!--Reference the autogenerated SignalR hub script. -->
    <script src="/signalr/hubs"></script>

<script type="text/javascript">
    $(function () {
        // Declare a proxy to reference the hub.
        var notifications = $.connection.messagesHub;

        //debugger;
        // Create a function that the hub can call to broadcast messages.
        notifications.client.updateMessages = function () {
            getAllMessages()

        };
        // Start the connection.
        $.connection.hub.start().done(function () {
            alert("connection started")
            getAllMessages();
        }).fail(function (e) {
            alert(e);
        });
    });


    function getAllMessages()
    {
        var tbl = $('#messagesTable');
        $.ajax({
            url: '/home/GetMessages',
            contentType: 'application/html ; charset:utf-8',
            type: 'GET',
            dataType: 'html'
        }).success(function (result) {
            tbl.empty().append(result);
        }).error(function () {

        });
    }
</script>

Hope this helps :)

like image 138
Aminul Avatar answered May 09 '23 14:05

Aminul