SignalR通过MVC控制器进行

时间:2016-05-12 22:56:12

标签: asynchronous model-view-controller signalr iprogress

Work Flow Scenario

上图代表我想要解决的方案。

根据我之前的经验,我知道进度报告模式可用于解决保持客户端更新的问题,但当时客户端正在直接与集线器通信,这意味着没有控制器或代码。

在上图中,问题是控制器需要先做东西才能调用DB。

此外,DB以文件的形式返回段,因此我添加了一个异步filesystemwatcher,用于在每次创建响应文件时通知我。

我们的目标是在收到响应段时继续向客户端浏览器提供响应段,直到我们到达响应结束时为止。

问题是:如何从控制器/服务方法触发signalR Hub并继续向客户端浏览器提供响应?

更新:

缩小问题范围

  1. 我的控制器调用服务方法

    string contents = await    _logService. ResponseFileWaiterAsync         (myData.guid.ToString());
    
  2. ResponseFilewaiterAsync方法中,创建第一个文件时,我会触发集线器

     BroadcastResponseToClient(responseFilePath, hubConnection);
    
         private void BroadcastResponseToClient(string responseFilePath, HubConnection hubConnection)
        {
            var hub = hubConnection.CreateHubProxy(typeof(string).Name);
            hubConnection
                .Start()
                .ContinueWith(_ => hub.Invoke("UpdateResponseToClient", ResponseHtml));
        }
    
  3. 集线器报告对客户端的响应以及在完成之前查找下一个文件

           public async Task UpdateResponseToClient(IProgress<string> progress,string filePath)
        {
            // Clients.Caller.appendReportToPage(ResponseHtml);
    
           string result = await _jbaseLoggingService.ResponseFileWaiterAsync(filePath);
            progress.Report(result);
        }
    
  4. 问题:如何从服务方法/控制器触发进度报告中心? 完成更新后我应该在哪里完成我的请求 - 是否应该返回控制器?

1 个答案:

答案 0 :(得分:0)

我想我可能已经解决了我的问题。我要做的第一件事就是渲染一个空占位符客户端,以便我可以启动客户端连接(集线器连接),然后在向控制器发送连接ID时对实际控制器方法进行AJAX调用。

  1. 控制器调用服务方法

    await  _logService.ResponseFileWaiterAsync(myData.guid.ToString(),clientId);
    
  2. 服务等待filewatcher通知创建/重命名的文件然后读取文件的内容并在clientId的帮助下将其传回客户端

     ResponseFileWaiterAsync(string responseFileName, string clientId)
     {
        //do stuff
        await DropFileHelper.WaitForResponseFileAsync(responseFilePath);
        contents = LoadResponseFile(responseFilePath);
        //do stuff
        Clients.Client(clientId).appendReportToPage(contents);
     }
    
  3. 使用

    在构造函数中加载客户端
    Clients = GlobalHost.ConnectionManager.GetHubContext<MyResponseHub>().Clients;
    

    appendReportToPage - 是客户端回调方法

    1. MyResponseHub为空。我所需要的只是确保SignalR有一个中心来完成它的魔法

                            public class JbaseResponseHub : Hub
                              {
                              }
      
      1. 客户端JS
    2.    $(function () {                   
              var _clientId;
              var hubProxy = $.connection.myResponseHub;        
              hubProxy.client.appendReportToPage = function (ResponseHtml) {
                  // Add the message to the page.                 
                  $('#responseBody').append( "<p>"+ResponseHtml+"</p>" + '</br></br></br>');
              };
      
              $.connection.hub.start()
                  .done(function () {
                      //alert('in hub start');
                      _clientId = $.connection.hub.id;
                      console.log('Now connected, connection ID=' + $.connection.hub.id);
                      //alert(_clientId);
      
                      $.ajax({
                          type: 'GET',
                          url: '/mycontroller/ProcessRequest',
                          data: { qs: $('#encryptedString').html().trim(), clientId: _clientId },
                          cache: false,
                          success: function (result) {
                              
                          }
                      });
                  })
                  .fail(function(){ console.log('Could not Connect!'); });
      
      });

      经验教训

      • 必须呈现客户端,以便它可以与集线器
      • 建立连接
      • 只要您有权访问客户
      • ,您就可以通过服务类/方法与客户进行通信

      有用的链接

      http://www.asp.net/signalr/overview/guide-to-the-api/hubs-api-guide-javascript-client#genproxy http://www.asp.net/signalr/overview/getting-started/tutorial-getting-started-with-signalr-and-mvc