如何使用SignalR向客户报告文件进度?

时间:2016-09-28 09:32:32

标签: c# asp.net asp.net-mvc events signalr

我编写了一个获取和优化文件的组件,并将其数据存储到数据库中。因为我希望这个类支持不同的环境(例如在控制台应用程序中使用它)所以我决定创建一些事件:

public interface IDataSeeder
{
    Task Seed(string fileName);
    event EventHandler<UserSucceedEventArgs> UserAdded;
    event EventHandler<UserErrorEventArgs> Error;
    event EventHandler<UserUpdateEventArgs> UserUpdated;
    event EventHandler<FinishDataSeederEventArgs> ProcessCompleted;
}

每个事件都会在Seed方法内的不同位置触发。它在我的控制台应用程序中就像一个魅力 现在我想在我的ASP.NET MVC应用程序中使用这个组件,为此我决定使用SignalR将事件的数据推送到客户端,所以我创建了一个这样的集线器:

public class ProgressHub : Hub
{
    public static void UserAdded(UserSucceedEventArgs e)
    {
        var ctx = GlobalHost.ConnectionManager.GetHubContext<ProgressHub>();
        ctx.Clients.All.userAdded(e);
    }

    public static void Error(UserErrorEventArgs e)
    {
        var ctx = GlobalHost.ConnectionManager.GetHubContext<ProgressHub>();
        ctx.Clients.All.error(e);
    }

    public static void UserUpdated(UserUpdateEventArgs e)
    {
        var ctx = GlobalHost.ConnectionManager.GetHubContext<ProgressHub>();
        ctx.Clients.All.userUpdated(e);
    }

    public static void ProcessCompleted(FinishDataSeederEventArgs e)
    {
        var ctx = GlobalHost.ConnectionManager.GetHubContext<ProgressHub>();
        ctx.Clients.All.processCompleted(e);
    }
}

然后我创建了这个动作方法来获取上传的文件并将其传递给我的组件:

[HttpPost]
public async Task<ActionResult> AddFromExcel(HttpPostedFileBase excelFile)
{
    if (excelFile != null)
    {
        var fileName = Utilities.UploadFile.UploadFile.UploadCommonFile(excelFile, "users");
        _dataSeeder.UserAdded += DataSeeder_Succeed;
        _dataSeeder.Error += DataSeeder_Error;
        _dataSeeder.UserUpdated += DataSeeder_Update;
        _dataSeeder.ProcessCompleted += DataSeeder_Finish;
        await _dataSeeder.Seed(Server.MapPath($"~/Content/Files/users/{fileName}"));
        return RedirectToAction("AddFromExcel");
    }
    return RedirectToAction("List");
}

private static void DataSeeder_Finish(object sender, FinishDataSeederEventArgs e)
{
    ProgressHub.ProcessCompleted(e);
}

private static void DataSeeder_Update(object sender, UserUpdateEventArgs e)
{
    ProgressHub.UserUpdated(e);
}

private static void DataSeeder_Error(object sender, UserErrorEventArgs e)
{
    ProgressHub.Error(e);
}

private static void DataSeeder_Succeed(object sender, UserSucceedEventArgs e)
{
    ProgressHub.UserAdded(e);
}

正如您在每个事件处理程序中看到的那样,我使用signalr hub通知客户端。

所有这个过程就像一个消息传递系统,但我不知道如何在Web应用程序中实现它。我的代码的一个缺陷是,在附加事件处理程序后,我立即将用户重定向到另一个操作方法,我知道它必须是异步进程,但我不知道如何使我的事件异步。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

您需要做的是将SignalR服务器调用与JavaScript函数匹配,这些函数会向连接的客户端显示结果:

<script type="text/javascript">
   // the proxy to your hub
   var hub = $.connection.ProgressHub;

   // the function that will be called when you call
   // ctx.Clients.All.userAdded(e);
   hub.client.userAdded = function (data) {
      // show the data
      alert(data);
   };

   // follow suit with the rest of the functions
   hub.client.error = function (data) {
      alert(data);
   };

   // etc

</script>