简体   繁体   English

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

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

I am currently trying to write some code that will accept some FTP details, get a file list, then allow the user to download the files. 我目前正在尝试编写一些代码,这些代码将接受一些FTP详细信息,获取文件列表,然后允许用户下载文件。

This all works fine, except that I have to wait for the files to finished downloading before it will do anything. 一切正常,除了我必须等待文件完成下载之后才能执行任何操作。 I am using an Asynchronous controller as I thought this was meant to help with this sort of thing. 我正在使用异步控制器,因为我认为这旨在帮助解决此类问题。

Please see a selection of my code below, I have left out all the code thats not relevant: 请在下面查看我的代码选择,我遗漏了所有与代码无关的代码:

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

It fires the FtpCompleted action perfectly fine, but the problem is this is meant to handle file transfers of potentially GB's of information. 它可以很好地触发FtpCompleted操作,但是问题是这意味着要处理潜在GB信息的文件传输。 I dont want the user to sit watching a spinning disc while they wait for the files to be downloaded. 我不希望用户在等待文件下载时坐下来观看旋转的光盘。 Hence the reason I was trying to redirect them to the Transfer Action, this action just displays a message telling them that the transfer may take a while and they will be notified once its complete. 因此,我尝试将他们重定向到“转移操作”的原因是,该操作仅显示一条消息,告诉他们转移可能需要一段时间,一旦转移完成,就会通知他们。 However this action never actually gets called. 但是,此操作实际上从未被调用。 I step through the code in debug and it calls it, but it never displays the message and it never gets to the browser according to FireBug. 我逐步调试了代​​码,并对其进行了调用,但是根据FireBug的说法,它从不显示消息,也不会到达浏览器。

Am I doing something stupid or is it just not possible to do this? 我是在做一些愚蠢的事情,还是只是做不到?

I would be grateful for any assistance people can offer here as I am completely stuck after browsing google and other posts on here. 我会很感激人们在这里可以提供的任何帮助,因为在浏览google和此处的其他帖子后,我完全陷入了困境。 Even my boss who is a much more experienced coder isnt sure how to handle this. 即使是经验丰富的编码员,我的老板也不确定该如何处理。

Thanks in advance, 提前致谢,

Gaz 加兹

As explained in the documentation an asynchronous controller action consists of 2 methods: 文档中所述,异步控制器操作包含2种方法:

  1. A method which returns void and has the Async suffix and the action name prefix 一种返回void并具有Async后缀和操作名称前缀的方法
  2. A method which returns ActionResult and has the Completed suffix and the action name prefix 返回ActionResult并具有Completed后缀和操作名称前缀的方法

The first method triggers asynchronous operation and returns immediately. 第一种方法触发异步操作并立即返回。 The second method is invoked once the entire operation has completed. 整个操作完成后,将调用第二种方法。

So here's are the correct action signatures: 所以这是正确的动作签名:

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

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

Now, if you don't want to freeze the browser during the entire operation you will have to invoke the first controller action using AJAX. 现在,如果您不想在整个操作过程中冻结浏览器,则必须使用AJAX调用第一个控制器操作。 Asynchronous controllers do not change anything in terms of the HTTP protocol. 异步控制器不会根据HTTP协议进行任何更改。 From the client perspective it is absolutely the same. 从客户的角度来看,这是绝对相同的。 The only difference with a standard controller action is that you are not jeopardizing a worker thread during the entire operation. 与标准控制器操作的唯一区别是,在整个操作过程中,您不会危害工作线程。 You are now relying on the IOCP (IO/Completion Ports) that are an OS artifact used by the WebClient . 现在,您依赖IOCP(IO /完成端口),它是WebClient使用的OS工件。 The idea is that when you start an IO intensive operation, an IOCP port is created and the controller action immediately returns the thread to the ASP.NET thread pool. 这个想法是,当您开始进行IO密集型操作时,将创建IOCP端口,并且控制器操作会立即将线程返回到ASP.NET线程池。 Then the operation could last for hours, and once it completes the IOCP is signaled, a pool is drawn from the thread pool and the Completed action is invoked on this thread. 然后该操作可能持续数小时,一旦完成IOCP信号,就会从线程池中提取一个池,并在该线程上调用Completed操作。 So in terms of threads it is very effective. 因此在线程方面非常有效。 But the total time of execution is absolutely the same as if you have used a standard controller action. 但是执行的总时间与使用标准控制器操作绝对相同。 Many people think that because Asynchronous Controller are called Asynchronous they run asynchronously from the client perspective. 许多人认为,由于异步控制器被称为异步,因此它们从客户端角度异步运行。 That's a false impression. 这是一个错误的印象。 Asynchronous actions don't make your operations miraculously run faster. 异步操作不会使您的操作奇迹般地运行得更快。 They are still perfectly synchronous from the client perspective, because that's how the HTTP protocol works. 从客户端的角度来看,它们仍然是完全同步的,因为这就是HTTP协议的工作方式。

So you have 2 possibilities: 因此,您有2种可能性:

  • Invoke the controller action using AJAX to avoid blocking the browser. 使用AJAX调用控制器操作,以避免阻塞浏览器。
  • Use COMET/PUSH technology in which it is the server that notifies the client. 使用COMET / PUSH技术,在该技术中,服务器将通知客户端。 For example in HTML5 there's the WebSockets standard which could be used to achieve that. 例如,在HTML5中,可以使用WebSockets标准来实现这一目标。 In the .NET world SignalR is a great framework which encapsulates this PUSH technology. 在.NET世界中, SignalR是一个很好的框架,它封装了该PUSH技术。

The second approach is recommended if you want a really effective solution. 如果您想要一个真正有效的解决方案,则建议使用第二种方法。

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

相关问题 在MVC4中,如何使用Url中的参数从控制器动作重定向到视图? - In MVC4, how to redirect to a view from a controller action with parameters in the Url? 如何从ASP.NET MVC中的同一操作重定向到另一个视图或外部站点? - How can I redirect to either another view or an external site from the same action in ASP.NET MVC? 如何从一个动作重定向到另一个动作,但在MVC 3中提供其参数? - How to redirect from an action to another action but provide its parameters in MVC 3? 如何在MVC4中做出自定义删除操作结果? - How can I make a custom delete action result in MVC4? .Net MVC4重定向到操作不按预期工作 - .Net MVC4 redirect to action not working as expected 是否有可能在MVC4中将会话值从动作转移到另一个动作? - Is it possible to get session values from action to another in MVC4? 如何重定向到在.net-core MVC中调用了另一个操作的View - How can I redirect to the View which called another action in .net-core MVC 完成动作后,如何在ASP.NET MVC中将某人从一个动作重定向到另一个动作? - How do I redirect someone from one action to another in ASP.NET MVC when an action has completed? 如何重定向到MVC网站我的父母行动? - How do I redirect to my parent action in MVC site? 如何从一个异步操作重定向到另一个(MVC5) - How do I redirect from one Async Action to Another (MVC5)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM