繁体   English   中英

如何从MVC4中的异步动作重定向到另一个动作

[英]How can I redirect to another action from my Asynchronous Action in MVC4

我目前正在尝试编写一些代码,这些代码将接受一些FTP详细信息,获取文件列表,然后允许用户下载文件。

一切正常,除了我必须等待文件完成下载之后才能执行任何操作。 我正在使用异步控制器,因为我认为这旨在帮助解决此类问题。

请在下面查看我的代码选择,我遗漏了所有与代码无关的代码:

  [HttpPost]
    public ActionResult FtpAsync(Downloads model)
    {
        var ftpAddress = model.Url;
        if (!ftpAddress.StartsWith("ftp://"))
            ftpAddress = String.Concat("ftp://", ftpAddress);

        var serverPath = Server.MapPath(ThumbnailSupport.CreateBaseVirtualPathForClient(StandardFileLinks.DropBoxLocation,
                                                                        _website.Client));

        if (!Directory.Exists(serverPath))
            Directory.CreateDirectory(serverPath);

        foreach (string file in model.SelectedFiles)
        {

            var webClient = new WebClient();

            AsyncManager.OutstandingOperations.Increment();

            AsyncManager.Parameters["FilesToDownload"] = model.SelectedFiles;
            webClient.Credentials = new NetworkCredential(model.Username, model.Password);

            webClient.DownloadFileAsync(new Uri(ftpAddress + "/" + file), serverPath + "\\" + file);
            AsyncManager.OutstandingOperations.Decrement();
        }

        return RedirectToAction("Transfer");

    }


    public ActionResult FtpCompleted(Downloads model)
    {
        return RedirectToAction("Complete");
    }

    public ActionResult Transfer()
    {
        return PartialView();
    }

它可以很好地触发FtpCompleted操作,但是问题是这意味着要处理潜在GB信息的文件传输。 我不希望用户在等待文件下载时坐下来观看旋转的光盘。 因此,我尝试将他们重定向到“转移操作”的原因是,该操作仅显示一条消息,告诉他们转移可能需要一段时间,一旦转移完成,就会通知他们。 但是,此操作实际上从未被调用。 我逐步调试了代​​码,并对其进行了调用,但是根据FireBug的说法,它从不显示消息,也不会到达浏览器。

我是在做一些愚蠢的事情,还是只是做不到?

我会很感激人们在这里可以提供的任何帮助,因为在浏览google和此处的其他帖子后,我完全陷入了困境。 即使是经验丰富的编码员,我的老板也不确定该如何处理。

提前致谢,

加兹

文档中所述,异步控制器操作包含2种方法:

  1. 一种返回void并具有Async后缀和操作名称前缀的方法
  2. 返回ActionResult并具有Completed后缀和操作名称前缀的方法

第一种方法触发异步操作并立即返回。 整个操作完成后,将调用第二种方法。

所以这是正确的动作签名:

[HttpPost]
public void FtpAsync(Downloads model)
{
    ...
}

public ActionResult FtpCompleted(Downloads model)
{
    return Content("Complete");
}    

现在,如果您不想在整个操作过程中冻结浏览器,则必须使用AJAX调用第一个控制器操作。 异步控制器不会根据HTTP协议进行任何更改。 从客户的角度来看,这是绝对相同的。 与标准控制器操作的唯一区别是,在整个操作过程中,您不会危害工作线程。 现在,您依赖IOCP(IO /完成端口),它是WebClient使用的OS工件。 这个想法是,当您开始进行IO密集型操作时,将创建IOCP端口,并且控制器操作会立即将线程返回到ASP.NET线程池。 然后该操作可能持续数小时,一旦完成IOCP信号,就会从线程池中提取一个池,并在该线程上调用Completed操作。 因此在线程方面非常有效。 但是执行的总时间与使用标准控制器操作绝对相同。 许多人认为,由于异步控制器被称为异步,因此它们从客户端角度异步运行。 这是一个错误的印象。 异步操作不会使您的操作奇迹般地运行得更快。 从客户端的角度来看,它们仍然是完全同步的,因为这就是HTTP协议的工作方式。

因此,您有2种可能性:

  • 使用AJAX调用控制器操作,以避免阻塞浏览器。
  • 使用COMET / PUSH技术,在该技术中,服务器将通知客户端。 例如,在HTML5中,可以使用WebSockets标准来实现这一目标。 在.NET世界中, SignalR是一个很好的框架,它封装了该PUSH技术。

如果您想要一个真正有效的解决方案,则建议使用第二种方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM