使用Signal R更新数据库更改时如何刷新视图 - javascript

我正在使用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();
       }
   }

即使这样做了,我的看法也没有刷新。我确定代码是多余的。可能有人向我展示了一种更好的方法。或者我要去哪里错了。

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

参考方案

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

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

我已经在this post...或V2 post中写过一些这样的博客

我在您的代码中看不到的是检测这些数据更新的安全代码。服务器上需要一些东西来检测更改并发出那些updateOnDashboard()调用。

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

根据您的评论进行更新:

我使用SinglaR来“实时”向Web客户端广播新添加的日志项目。在服务器端,我有一个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中。此可观察数组在HTML中使用Knockout foreach绑定(请参见here)。因此,对于数据更新,我不使用Razor和ASP.Net来生成HTML。这是最初发送的视图的全部内容,该视图中包含数据绑定并引用了我的Javascript / Typescript。与上述喜欢的博客文章中记录的内容非常相似。

剃刀付款集成->如何通过关闭按钮X检测剃刀付款模型是否关闭 - javascript

当用户关闭而无需付款时,我在CI框架中使用Razorpay,请创建razor支付模型,然后取消订单,我希望按状态更改为已取消的状态触发查询。所以我怎么能检测到这一点。我已经通过单击jQuery单击关闭功能但无法使用... javascript大神给出的解决方案 Razorpay提供了JS方法来检测模式关闭。您编写的任何JS代码都不会在结帐页面上运行,因为它是…

用多个通配符替换正则表达式可在PHP中工作,而不能在JavaScript中工作 - javascript

我正在尝试为两个Markdown解析器实现中心对齐:在Parsedown的PHP中(成功)在Bootstrap Markdown的JavaScript中(未成功)我遵循并找到最简单的方法是使用最终的HTML输出,只需将内联样式捕捉到标签上即可。以下正则表达式可以满足我的需要,它会根据需要将style="text-align:center;"…

JavaScript将PHP中的字符串和整数传递给函数 - javascript

我正在尝试将字符串和整数都传递到同一函数中,但是引号引起了问题。我发现错误出在echo $q->info部分,我必须在此代码上使用双引号。有人可以帮我写这个$q->info,但不能获得真正的价值吗?到目前为止,我的代码是<td><a href="javascript:add(<?php echo $q->i…

在提交时在表单操作中获取变量丢失 - javascript

            当表单由onchange事件提交时,它不会保留get变量view。任何想法为什么会发生这种情况?提交后,这是它进入的网址,index?month=February&year=2014<form action="index?view=list" class="pure-form pure-fo…

html中的python代码和javascript代码之间的执行顺序是什么 - javascript

我正在使用bottle框架动态列出用于编辑任务的链接,从逻辑上说,行是具有多个(id,任务,状态)的元组的集合,下面的代码应该给出第一个链接http://localhost:8217/edit/1 第二个环节http://localhost:8217/edit/2 如此反复但是所有的链接都是http://localhost:8217/edit/5 因此我怀疑…