پیام Watch Application با DataBase Notifications توسط SignalR در MVC

در این مقاله قصد داریم در موردWatch Application ها به وسیله ی SignalR ها صحبت کنیم .SignalR یک کتابخانه است که ارائه دهنده فرآیند اضافه کردن به روز رسانی در زمان واقعی در برنامه های تحت وب است.در واقع قابلیت های وب سرور به طور خودکار پاسخ به مشتریان متصل را به جای داشتن انتظار سرور برای درخواست داده های جدید ارسال می کند.

پیام Watch Application با DataBase Notifications توسط SignalR در MVC

Message Watch یک برنامه ی تحت وب است، که داده هایی که از دیتابیس می گیرد و یا داده های به روز رسانی شده را در زمان واقعی در برنامه های مختلف تحت وب از راه اطلاعیه ی پایگاه داده و SignalR می تواند این پیغام ها را در زمان واقعی برای کاربر به روز رسانی کند.

قدم اول:تنظیم کردن پایگاه داده:یک DataBase به نام SignalRDataBase می سازیم و جدول های زیر را درست می کنیم.

1- Application

2- logLevel

3- MessageLog

OperationCode-4

Enable Broker رادیتابیس true تنظیم می کنیم.

قدم دوم:Visual Studio را باز کنید و سپس ASP.Net Web را انتخاب می کنیم، و سپس یک صفحه ی MVC انتخاب می نمایید.به صورت زیر:

روی application خود راست کلیک نمایید و ManageNuGet Packages را انتخاب می کنید، و در قسمت

آنلاین Microsoft Asp.NET SignalR را انتخاب می کنید به صورت تصویر زیر:

بعد از نصب کردن داخل فولدر Reference ،کتابخانه های مربوط به SignalR وجو دارد.

قدم سوم:داخل کلاس Startup.cs و Map SignalR به صورت زیر خواهد بود:

using Microsoft.Owin;
using Owin;

[assembly: OwinStartupAttribute(typeof(MessageWatch.Startup))]
namespace MessageWatch
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}

یک کلاس به نام MessageLog.cs می سازید(تمام خاصیت هایی را که می خواهید در سمت کلاینت به روز رسانی شود را اضافه می کنید.)

public class MessageLog
{
    public string Name { get; set; }

    public int EventID { get; set; }

    public string LogLevelName { get; set; }

    public string OperationCodeName { get; set; }

    public string ServerName { get; set; }

    public string ComponentName { get; set; }

    public string SubComponentName { get; set; }
}

روی Solution راست کلیک کرده و کلاس SignalR Hub را اضافه می کنید (نام کلاس را NotificationHub.cs) می گذارید، مسولیت این تابع ارسال به روز رسانی به مشتریان است.

یک متد به نام GetAllMessagesLog در کلاس NotificationHub می نویسید اطلاعات مورد نیاز را از دیتابیس بیرون می کشد و پاسخ را به تابع مورد نظر ارسال خواهد کرد.

در این تابع ما در حال راه اندازی وابستگی پایگاه داده، و جذب کردن تمام سوابق از پایگاه داده هستیم.

public IEnumerable<MessageLog> GetAllMessagesLog()
   {
       string conStr = ConfigurationManager.ConnectionStrings["SignalRDB"].ConnectionString;
       SqlConnection connection = new SqlConnection(conStr);

       string query = "SELECT Message,EventID,LL.Name as LogLevelID,OC.Name as OperationCodeID,ML.ServerName,ML.ComponentName,ML.SubComponentName FROM [dbo].[MessageLog] ML inner join [dbo].[LogLevel] LL on ML.LogLevelID = LL.ID inner join [dbo].[OperationCode] OC on ML.OperationCodeID = OC.ID";
       SqlDependency.Start(conStr);
       SqlCommand command = new SqlCommand(query, connection);
       SqlDependency dependency = new SqlDependency(command);

       //If Something will change in database and it will call dependency_OnChange method.
       dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
       connection.Open();
       SqlDataAdapter da = new SqlDataAdapter(command);
       DataTable dt = new DataTable();
       da.Fill(dt);

       List<MessageLog> messageList = new List<MessageLog>();
       for (int i = 0; i < dt.Rows.Count; i++)
       {
           MessageLog ml = new MessageLog();
           ml.Name = dt.Rows[i]["Message"].ToString();
           ml.EventID = Convert.ToInt32(dt.Rows[i]["EventID"].ToString());
           ml.LogLevelName = dt.Rows[i]["LogLevelID"].ToString();
           ml.OperationCodeName = dt.Rows[i]["OperationCodeID"].ToString();
           ml.ServerName = dt.Rows[i]["ServerName"].ToString();
           ml.ComponentName = dt.Rows[i]["ComponentName"].ToString();
           ml.SubComponentName = dt.Rows[i]["SubComponentName"].ToString();
           messageList.Add(ml);
       }
       return messageList;

   }

حالا دو متد زیر را اضافه می کنید، زمانی که بخواهید چیزی را در دیتابیس تغییر دهید.

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

           SendNotifications();
       }
   }
   private void SendNotifications()
   {
       IEnumerable<MessageLog> messageList = GetAllMessagesLog();

       IHubContext context = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
       context.Clients.All.broadcastMessage(messageList);//Will update all the clients with message log.

   }

حالا به فولدر Controller بروید وHomeController  را باز کنید و یک متد مثل زیر را اضافه کنید:

public ActionResult GetNotification()
    {
        return View();
    }

یک View به صورت زیر می سازید:

View جدیدی را که ساخته اید را باز کنید و Css زیر را در قسمت Head اضافه کنید:

<style type="text/css">.container {
            background-color: #99CCFF;
            border: thick solid #808080;
            padding: 20px;
            margin: 20px;
        }</style>

اسکریپت SignalRرا در GetNotification.cshtml اضافه کنید:

 var ew = $.connection.notificationHub;
            //This method will fill all the Messages in case of any database change.
            //Server side code will call this function to update information client.
            ew.client.broadcastMessage = function (messageLogs) {
                // Html encode display name and message.
                var i = 0;
                if ($('#hdnValue').val() == 1) {
                    $messageTableBody.empty();

                    $.each(messageLogs, function () {
                        var encodedName = messageLogs[i].Name;
                        var encodedEvent = messageLogs[i].EventID;
                        var encodedLogLevel = messageLogs[i].LogLevelName;
                        var encodedOCode = messageLogs[i].OperationCodeName;
                        var encodedServerName = messageLogs[i].ServerName;
                        var encodedCompName = messageLogs[i].ComponentName;
                        var encodedSubCompName = messageLogs[i].SubComponentName;
                        if (encodedLogLevel == "Fatal") {
                            $messageTableBody.append('<tr style="background-color:Red"><td>' + encodedName + '</td><td>' + encodedEvent + '</td><td>' + encodedLogLevel + '</td><td>' + encodedOCode + '</td><td>' + encodedServerName + '</td><td>' + encodedCompName + '</td><td>' + encodedSubCompName + '</td></tr>');
                        }
                        if (encodedLogLevel == "Warning") {
                            $messageTableBody.append('<tr style="background-color:Yellow"><td>' + encodedName + '</td><td>' + encodedEvent + '</td><td>' + encodedLogLevel + '</td><td>' + encodedOCode + '</td><td>' + encodedServerName + '</td><td>' + encodedCompName + '</td><td>' + encodedSubCompName + '</td></tr>');
                        }
                        else {
                            $messageTableBody.append('<tr><td>' + encodedName + '</td><td>' + encodedEvent + '</td><td>' + encodedLogLevel + '</td><td>' + encodedOCode + '</td><td>' + encodedServerName + '</td><td>' + encodedCompName + '</td><td>' + encodedSubCompName + '</td></tr>');
                        }
                        i = i + 1;
                    });
                }
            };

اگر می خواهید تمام پیام ها در اولین بار بار گذاری شود کد زیر را می نویسید:

$.connection.hub.start().done(function () {

            ew.server.getAllMessagesLog().done(function (messageLogs) {
                var i = 0;
                if ($('#hdnValue').val() == 1) {
                    $messageTableBody.empty();
                    $.each(messageLogs, function () {
                        var encodedName = messageLogs[i].Name;
                        var encodedEvent = messageLogs[i].EventID;
                        var encodedLogLevel = messageLogs[i].LogLevelName;
                        var encodedOCode = messageLogs[i].OperationCodeName;
                        var encodedServerName = messageLogs[i].ServerName;
                        var encodedCompName = messageLogs[i].ComponentName;
                        var encodedSubCompName = messageLogs[i].SubComponentName;
                        if (encodedLogLevel == "Fatal") {
                            $messageTableBody.append('<tr style="background-color:Red"><td>' + encodedName + '</td><td>' + encodedEvent + '</td><td>' + encodedLogLevel + '</td><td>' + encodedOCode + '</td><td>' + encodedServerName + '</td><td>' + encodedCompName + '</td><td>' + encodedSubCompName + '</td></tr>');
                        }
                        if (encodedLogLevel == "Warning") {
                            $messageTableBody.append('<tr style="background-color:Yellow"><td>' + encodedName + '</td><td>' + encodedEvent + '</td><td>' + encodedLogLevel + '</td><td>' + encodedOCode + '</td><td>' + encodedServerName + '</td><td>' + encodedCompName + '</td><td>' + encodedSubCompName + '</td></tr>');
                        }
                        else {
                            $messageTableBody.append('<tr><td>' + encodedName + '</td><td>' + encodedEvent + '</td><td>' + encodedLogLevel + '</td><td>' + encodedOCode + '</td><td>' + encodedServerName + '</td><td>' + encodedCompName + '</td><td>' + encodedSubCompName + '</td></tr>');
                        }
                        i = i + 1;
                    });
                }
            });
        });

 

کد کامل در صفحه ی   GetNotifiaction.cs به صورت زیر خواهد بود:

@{
    Layout = null;
}

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Message Watch</title>
    <style type="text/css">
        .container {
            background-color: #99CCFF;
            border: thick solid #808080;
            padding: 20px;
            margin: 20px;
        }
    </style>
    <style>
        body {
            font-family: 'Segoe UI', Arial, Helvetica, sans-serif;
            font-size: 16px;
        }

        #messageTable table {
            border-collapse: collapse;
        }

            #messageTable table th, #messageTable table td {
                padding: 2px 6px;
            }

            #messageTable table td {
                text-align: right;
            }

        #messageTable .loading td {
            text-align: left;
        }
    </style>
</head>
<body>
    <div class="container">
        <div id="messageTable">
            <table border="1">
                <thead>
                    <tr><th>Message< /th><th>EventID</th><th>Component Name</th><th>OperationCodeName</th><th>ServerName</th><th>ComponentName</th><th>SubComponentName</th></tr>
                </thead>
                <tbody>
                  
                </tbody>
            </table>
            <input type="button" id="btnPause" name="Pause" value="Pause" />
            <input type="button" id="btnResume" name="Resume" value="Resume" />
            <input id="hdnValue" type="hidden" value="1" />

        </div>
    </div>
   
    <script src="~/Scripts/jquery-1.10.2.js"></script>
    <script src="~/Scripts/jquery-1.10.2.min.js"></script>
    <script src="~/Scripts/jquery.signalR-2.2.0.js"></script>
    <script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
    <script src="~/signalr/hubs"></script>
    <script type="text/javascript">
        $(function () {
            $('#btnPause').click(function () {
                $('#hdnValue').val(0);
            });
            $('#btnResume').click(function () {
                $('#hdnValue').val(1);
            });
            var $messageTable = $('#messageTable');
            var $messageTableBody = $messageTable.find('tbody');
            // Declare a proxy to reference the hub.
            var ew = $.connection.notificationHub;
            //This method will fill all the Messages in case of any database change.
            ew.client.broadcastMessage = function (messageLogs) {
                // Html encode display name and message.
                var i = 0;
                if ($('#hdnValue').val() == 1) {
                    $messageTableBody.empty();

                    $.each(messageLogs, function () {
                        var encodedName = messageLogs[i].Name;
                        var encodedEvent = messageLogs[i].EventID;
                        var encodedLogLevel = messageLogs[i].LogLevelName;
                        var encodedOCode = messageLogs[i].OperationCodeName;
                        var encodedServerName = messageLogs[i].ServerName;
                        var encodedCompName = messageLogs[i].ComponentName;
                        var encodedSubCompName = messageLogs[i].SubComponentName;
                        if (encodedLogLevel == "Fatal") {
                            $messageTableBody.append('<tr style="background-color:Red"><td>' + encodedName + '</td><td>' + encodedEvent + '</td><td>' + encodedLogLevel + '</td><td>' + encodedOCode + '</td><td>' + encodedServerName + '</td><td>' + encodedCompName + '</td><td>' + encodedSubCompName + '</td></tr>');
                        }
                        if (encodedLogLevel == "Warning") {
                            $messageTableBody.append('<tr style="background-color:Yellow"><td>' + encodedName + '</td><td>' + encodedEvent + '</td><td>' + encodedLogLevel + '</td><td>' + encodedOCode + '</td><td>' + encodedServerName + '</td><td>' + encodedCompName + '</td><td>' + encodedSubCompName + '</td></tr>');
                        }
                        else {
                            $messageTableBody.append('<tr><td>' + encodedName + '</td><td>' + encodedEvent + '</td><td>' + encodedLogLevel + '</td><td>' + encodedOCode + '</td><td>' + encodedServerName + '</td><td>' + encodedCompName + '</td><td>' + encodedSubCompName + '</td></tr>');
                        }
                        i = i + 1;
                    });
                }
            };

            //This method will fill all the Messages initially
            $.connection.hub.start().done(function () {
             
                ew.server.getAllMessagesLog().done(function (messageLogs) {
                    var i = 0;
                    if ($('#hdnValue').val() == 1) {
                        $messageTableBody.empty();
                        $.each(messageLogs, function () {
                            var encodedName = messageLogs[i].Name;
                            var encodedEvent = messageLogs[i].EventID;
                            var encodedLogLevel = messageLogs[i].LogLevelName;
                            var encodedOCode = messageLogs[i].OperationCodeName;
                            var encodedServerName = messageLogs[i].ServerName;
                            var encodedCompName = messageLogs[i].ComponentName;
                            var encodedSubCompName = messageLogs[i].SubComponentName;
                            if (encodedLogLevel == "Fatal") {
                                $messageTableBody.append('<tr style="background-color:Red"><td>' + encodedName + '</td><td>' + encodedEvent + '</td><td>' + encodedLogLevel + '</td><td>' + encodedOCode + '</td><td>' + encodedServerName + '</td><td>' + encodedCompName + '</td><td>' + encodedSubCompName + '</td></tr>');
                            }
                            if (encodedLogLevel == "Warning") {
                                $messageTableBody.append('<tr style="background-color:Yellow"><td>' + encodedName + '</td><td>' + encodedEvent + '</td><td>' + encodedLogLevel + '</td><td>' + encodedOCode + '</td><td>' + encodedServerName + '</td><td>' + encodedCompName + '</td><td>' + encodedSubCompName + '</td></tr>');
                            }
                            else {
                                $messageTableBody.append('<tr><td>' + encodedName + '</td><td>' + encodedEvent + '</td><td>' + encodedLogLevel + '</td><td>' + encodedOCode + '</td><td>' + encodedServerName + '</td><td>' + encodedCompName + '</td><td>' + encodedSubCompName + '</td></tr>');
                            }
                            i = i + 1;
                        });
                    }
                });
            });
        });

    </script>
</body>


اگر برنامه را اجرا کنید خروجی زیر را خواهید دید:

بروزرسانی بعضی از اطلاعات در جدول MessageLog

Insert into MessageLog values(4,102,3,2,13,3467,'Test123','DocClass.dll','GetData()','345','User is unable to get data','Sample Stack Trace',getdate())

دو دکمه به نام Pause و Resume وجود دارد که برای توقف و شروع دوباره ی داده در زمان واقعی وجود دارد.

فایل های ضمیمه