0

工作流程场景

上图代表我要解决的场景。

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

在上图中,问题是控制器在调用数据库之前需要做一些事情。

此外,数据库以文件的形式返回段,因此我添加了一个异步文件系统观察器,用于在每次创建响应文件时通知我。

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

问题是:如何从控制器/服务方法触发 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 回答 1

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);
     }
    

客户端使用在构造函数中加载

Clients = GlobalHost.ConnectionManager.GetHubContext<MyResponseHub>().Clients;

appendReportToPage - 是客户端回调方法

  1. MyResponseHub 为空。我所需要的只是确保 SignalR 有一个集线器来发挥它的魔力

                          public class JbaseResponseHub : Hub
                            {
                            }
    
    1. 客户端JS

   $(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

于 2016-05-17T19:18:27.627 回答