【问题标题】:How to refresh view when using signal r to update on database change使用信号器更新数据库更改时如何刷新视图
【发布时间】:2015-11-25 14:22:05
【问题描述】:

我正在使用 mvc,我有一个仪表板,我使用了 charthelper 和 bootstrap 管理图表。现在我想更新有关数据库更改的数据。我正在尝试使用信号 R。

之前

我使用存储库从数据库中获取数据。所以有服务文件夹,它有它的方法。

现在。

我不确定该怎么做。 但到目前为止我所做的是创建了一个集线器类, 返回

public static void Send()
   {
       IHubContext context = GlobalHost.ConnectionManager.GetHubContext<DashboardHub>();
       context.Clients.All.updateOnDashboard();
   }

正在观看

<script>
$(function () {
    // Declare a proxy to reference the hub.
    var chat = $.connection.dashboardHub;
    $.connection.hub.logging = true;

    chat.client.foo = function () { };

    //debugger;
    // Create a function that the hub can call to broadcast messages.
    chat.client.updateOnDashboard = function () {
        getAllDashboardUpdates()
    };
    $.connection.hub.start().done(function () {
        getAllDashboardUpdates();

        console.log('Now connected, connection ID=' + $.connection.hub.id);
    })
        .fail(function () { console.log('Could not connect'); });;

    //$.connection.hub.stop();
});

function getAllDashboardUpdates() {
    $.ajax({
        url: '/Dasdhboard/Index',
        contentType: 'application/html ; charset:utf-8',
        type: 'GET',
        dataType: 'html'
    }).success(function (result) {
        //$("#refTable").html(result);
    }).error(function () {
    });
}

控制器方法

public ActionResult Index(int? page)
    {
        IEnumerable<test> newlist = null;

        newlist = GetAlltest();
        var data = dashboardService.GetDashboardData(page, User);
        if (newlist != null)
        {
            return View(data);
        }
        return View(data);
    }

寻找依赖

public IEnumerable<test> GetAlltest()
   {

       var messages = new List<test>();
       using (var connection = new SqlConnection(_connString))
       {
           connection.Open();
           using (var command = new SqlCommand(@"SELECT [id],[testid] FROM [dbo].[test]", connection))
           {
               command.Notification = null;
               SqlDependency.Start(_connString);
               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 test { id = (int)reader["id"] });
               }
           }

       }
       return messages;
   }

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

即使这样做了,我的视图也没有刷新。我确定代码是多余的。有人可以告诉我一个更好的方法来做到这一点。或者我哪里出错了。

这只是一种方法。我也有两张图表。

【问题讨论】:

    标签: javascript c# ajax model-view-controller signalr


    【解决方案1】:

    如果我正确理解您的代码,您当前建立了一个 SingalR 连接,并且如果在客户端接收到 updateOnDashboard() 触发 AJAX 调用以从服务器获取完整的 HTML 视图,并使用 jQuery 将其插入 DOM。

    我会更改它,以便 updateOnDashboard() 也接收您的新值并在客户端呈现这些值,而不是再次调用服务器以获取 HTML 代码。我会更进一步,为这些值创建一个 Javascript 视图模型,并使用 Knockout 将您的仪表板元素数据绑定到视图模型。然后 updateOnDashboard() 只需将这些值(参数)推送到视图模型中,HTML 通过 Knockout 获取更新。

    我已经在 this post...V2 post 上写过一些博客

    我在您的代码中没有看到检测这些数据更新的代码的和平。您需要在服务器上检测更改并发送那些 updateOnDashboard() 调用。

    还请注意,您的 Hub 方法 Send() 不会在任何地方使用。集线器方法仅用于客户端到服务器的调用(传入的服务器调用)。你可能没有这些,所以你不需要集线器方法——我猜。

    根据您的评论更新:

    我使用 SinglaR 将新添加的日志项“实时”广播到网络客户端。在服务器端,我有一个 singleton 来测试新数据并使用 SignalR 将它们广播到 Web 客户端。代码如下:

    /// <summary>
    /// Singleton that periodically checks the log database for new messages and broadcasts them to all
    /// connected web-clients (SignalR).
    /// </summary>
    public class LiveMessageTicker : ILiveMessageTicker, IRegisteredObject
    {
        private readonly TimeSpan updateInterval = TimeSpan.FromMilliseconds(2000);
        private readonly ILogEntriesRepository repository;
        private Guid lastLogEntryId = Guid.Empty;
        private readonly SemaphoreSlim checkSemaphore = new SemaphoreSlim(1, 2);
        private Timer checkTimer;
        private readonly IHubContext hub;
    
        /// <summary>
        /// Initializes a new instance of the <see cref="LiveMessageTicker"/> class.
        /// </summary>
        /// <param name="repository">The database repository to use.</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        public LiveMessageTicker(ILogEntriesRepository repository)
        {
            if (repository == null) { throw new ArgumentNullException(nameof(repository)); }
    
            this.repository = repository;
    
            // Register this instance to in ASP to free it up on shutdown
            HostingEnvironment.RegisterObject(this);
    
            // Get the server-side SignalR hub
            hub = GlobalHost.ConnectionManager.GetHubContext<ServerMonitoringHub>(); 
    
            // Configure a Timer that calls CheckForNewMessages all 2 sec's
            checkTimer = new Timer(CheckForNewMessages, null, TimeSpan.Zero, updateInterval);
        }
    
        /// <summary>
        /// Stops this instance.
        /// </summary>
        /// <param name="immediate">if set to <c>true</c> immediatelly.</param>
        /// <seealso cref="IRegisteredObject"/>
        public void Stop(bool immediate)
        {
            checkTimer.Dispose();
            checkTimer = null;
    
            HostingEnvironment.UnregisterObject(this);
        }
    
        private void CheckForNewMessages(object state)
        {
            if (checkSemaphore.Wait(500))
            {
                try
                {
                    // Get new log entries
                    var newLogEntries = repository.GetNewLogEntries(lastLogEntryId).ToList();
    
                    // If there arent any new log entries
                    if (!newLogEntries.Any())
                    {
                        return;
                    }
    
                    lastLogEntryId = newLogEntries.Last().Id;
    
                    // Convert DB entities into DTO's for specific client needs
                    var logEntries = newLogEntries.Select(l => new
                    {
                        id = l.Id,
                        correlationId = l.CorelationIdentifier,
                        messageId = l.MessageId,
                        time = l.Time.ToLocalTime(),
                        level = (int)l.Level,
                        messageText = l.Message,
                        additionalData = l.AdditionalData.Select(a => new { name = a.Name, value = a.Value }).ToArray(),
                        tags = l.Tags.Select(t => t.Name).ToArray(),
                        channel = l.Channel.Name,
                        username = l.Username,
                        workstation = l.WorkstationName
                    }).ToList();
    
                    // Broadcast all new log entries over SignalR
                    hub.Clients.All.addLogMessages(logEntries);
                }
                finally
                {
                    checkSemaphore.Release();
                }
            }
        }
    }
    

    这一切都从Global.asax.cs 开始,在那里我创建了上述类的一个实例(它通过 ASP.Net 注册自己,以便稍后使用HostingEnvironment.RegisterObject(this) 正确停止)。

    请注意,我不会将呈现的 HTML 代码或视图推送到客户端。我将数据作为 JSON 推送。服务器不渲染它,但客户端渲染它。为了在客户端上呈现它,我使用了一个 Javascript/Typescript 视图模型,它在 Knockout ObservableArray 中收集传入的消息。这个 observablearray 使用 Knockout foreach 绑定到 HTML(参见 here)。所以对于数据更新,我不使用 Razor 和 ASP.Net 来生成 HTML。这是最初发送的视图的所有部分,其中包含数据绑定并引用我的 Javascript/Typescript。它与上面喜欢的博客文章中记录的非常相似。

    【讨论】:

    • 在我让控制器操作调用接口方法从存储库获取数据之前。所以这很简单。现在我想与信号 r 集成。我想我需要有一个信号 r 集线器才能开始。集线器方法应该是什么?我可以从控制器调用它吗?我如何从控制器返回我的视图?
    • 用服务器端更新了我的答案以及有关客户端的更多信息。
    • 我对淘汰赛一无所知。所以等待更多的答案。
    • 淘汰赛只是一种方式。您可以使用 jQuery 将值更新到您的 HTML 中,甚至可以使用您的方法从服务器获取 HTML(使用 Razor 视图进行操作)。关键是您需要运行服务器代码并将数据/事件从服务器主动推送到客户端。 hub.Clients.All必须从服务器调用。这是在您的 Send() 方法中完成的,但谁调用了 Send() 方法。一些后台线程/工作者/等必须调用这个东西,以便服务器发起推送到客户端。
    • 我有'chat.client.updateOnDashboard = function () { getAllDashboardUpdates() };'在我看来,脚本中的方法在集线器 Send() 方法中执行了他的断点。不知道我做事是否正确
    猜你喜欢
    • 2014-01-22
    • 1970-01-01
    • 2013-05-12
    • 2014-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-03
    相关资源
    最近更新 更多