【问题标题】:SignalR - Javascript Hub ProxiesSignalR - Javascript 集线器代理
【发布时间】:2017-06-10 18:34:52
【问题描述】:

当您使用 SignalR 时,您需要在 HTML 中引用以下两个脚本:

<script src="~/Scripts/jquery.signalR-1.0.0.js"></script>
<script src="/signalR/hubs"></script>

第二个是自动生成的 JavaScript hub 代理。一切正常。但是,如果 JavaScript Hub 代理生成以某种方式被禁用,可能通过设置 DisableJavaScriptProxies 属性 (https://github.com/SignalR/SignalR/commit/7e974f4e92551a26f3e3e0a166e1dbf6c064e850) 会发生什么。当 JavaScript 代理生成被禁用并且您尝试在 HTML 中引用 /signalr/hubs 时,它会给出 JavaScript 错误:

Uncaught Error: SignalR: JavaScript Hub proxy generation has been disabled.

当我在浏览器中浏览到该路径时,响应是:

throw new Error('SignalR: JavaScript Hub proxy generation has been disabled.')

如果禁用了 JavaScript 代理生成,$.connection.myHub.client JavaScript 代码将如何工作?我还需要做些什么才能使其正常工作?我得到的 JavaScript 错误是

Uncaught TypeError: cannot read property 'client' of undefined.

【问题讨论】:

    标签: signalr signalr-hub


    【解决方案1】:

    您可以自己创建代理。见here

    这也在 SignalR 源中的示例项目中完成。请参阅鼠标跟踪示例。 JS 为它(来自here):

    /// <reference path="../../Scripts/jquery-1.8.2.js" />
    /// <reference path="../../Scripts/jquery.signalR.js" />
    
    $(function () {
        var hubConnection = $.hubConnection('/signalr', { qs: 'test=1', logging: false, useDefaultPath: false }),
            hub = hubConnection.createHubProxy('mouseTracking');
    
        hub.on('move', updateCursor);
    
        function updateCursor(id, x, y) {
            var e = document.getElementById(id);
            if (!e) {
                e = $('<div id="' + id + '"><i class="icon-screenshot"></i>' + id + '</div>').appendTo(document.body);
                e.css('position', 'absolute');
            }
            else {
                e = $(e);
            }
            e.css({ left: x + 15, top: y + 15 });
        }
    
        hubConnection.logging = true;
        hubConnection.start({ transport: activeTransport })
            .pipe(function () {
                return hub.invoke('join');
            })
            .pipe(function () {
                $(document).mousemove(function (e) {
                    hub.invoke('move', e.pageX, e.pageY);
                    updateCursor(hub.state.id, e.pageX, e.pageY);
                });
            });
    });
    

    【讨论】:

      【解决方案2】:

      您可能在 Startup 类中禁用了它,如下所示:

      public partial class Startup
          {
              public void Configuration(IAppBuilder app)
              {
                  ConfigureAuth(app);
      
                  var hubConfiguration = new HubConfiguration();
                  hubConfiguration.EnableDetailedErrors = true;
                  hubConfiguration.EnableJavaScriptProxies = false;
                  app.MapSignalR("/signalr", hubConfiguration);
              }
          }
      

      我有上面的代码。删除/注释掉这一行: hubConfiguration.EnableJavaScriptProxies = false;应该给你代理生成。

      public partial class Startup
              {
                  public void Configuration(IAppBuilder app)
                  {
                      ConfigureAuth(app);
      
                      var hubConfiguration = new HubConfiguration();
                      hubConfiguration.EnableDetailedErrors = true;
                      app.MapSignalR("/signalr", hubConfiguration);
                  }
              }
      

      【讨论】:

        【解决方案3】:

        对于所有偶然发现此问题的人。这似乎是设计使然,甚至 SignalR 实用程序也只生成服务器代理方法。

        它不会创建客户端方法,即使您有一个强类型集线器(客户端接口)。

        因此,唯一正确的答案应该是您应该生成小函数,如 Microsoft 所记录的那样。

        如股票行情示例:

         $.connection.hub.start()
                .then(init)
                .then(function () {
                    return ticker.server.getMarketState();
                })
                .done(function (state) {
                    if (state === 'Open') {
                        ticker.client.marketOpened();
                    } else {
                        ticker.client.marketClosed();
                    }
        

        股票代码本身是这样定义的 公共类 StockTickerHub : 集线器

        和界面

         public interface IClientStock
            {
                void MarketOpened();
                void MarketClosed();
                void MarketReset();
                void UpdateStockPrice(Stock stock);
            }
        

        因此,对于每个客户端代理方法,重复此操作。这不应破坏任何机构的项目目标。

        $.extend(ticker.client, {
                updateStockPrice: function (stock) {
                    var displayStock = formatStock(stock),
                        $row = $(rowTemplate.supplant(displayStock)),
                        $li = $(liTemplate.supplant(displayStock)),
                        bg = stock.LastChange < 0
                                ? '255,148,148' // red
                                : '154,240,117'; // green
        
                    $stockTableBody.find('tr[data-symbol=' + stock.Symbol + ']')
                        .replaceWith($row);
                    $stockTickerUl.find('li[data-symbol=' + stock.Symbol + ']')
                        .replaceWith($li);
        
                    $row.flash(bg, 1000);
                    $li.flash(bg, 1000);
                },
        
                marketOpened: function () {
                    $("#open").prop("disabled", true);
                    $("#close").prop("disabled", false);
                    $("#reset").prop("disabled", true);
                    scrollTicker();
                },
        

        【讨论】:

          相关资源