通过AJAX调用ASP.NET MVC控制器FileContent ActionResult

通过AJAX调用ASP.NET MVC控制器FileContent ActionResult,asp.net,asp.net-mvc,ajax,Asp.net,Asp.net Mvc,Ajax,设置: 控制器包含一个方法public ActionResult SaveFile(),该方法返回一个FileContentResult 什么有效: 该视图包含一个表单,该表单提交到此操作。结果是出现以下对话框: 什么不起作用: 该视图包含一些javascript,用于对表单将发布的同一控制器操作执行AJAX调用。响应不触发前面提到的对话框,甚至不触发AJAX成功函数,而是触发AJAX错误函数,XMLHttpRequest.responseText包含文件响应 我需要做什么: 使用AJAX请求文

设置

控制器包含一个方法
public ActionResult SaveFile()
,该方法返回一个
FileContentResult

什么有效

该视图包含一个表单,该表单提交到此操作。结果是出现以下对话框:

什么不起作用

该视图包含一些javascript,用于对表单将发布的同一控制器操作执行AJAX调用。响应不触发前面提到的对话框,甚至不触发AJAX成功函数,而是触发AJAX错误函数,
XMLHttpRequest.responseText
包含文件响应

我需要做什么:


使用AJAX请求文件,结果与提交表单时相同。如何使AJAX请求提供提交表单所显示的对话框?

下面是我编写的一个快速示例。这就是LukLed在调用SaveFile时提到的概念,但不要通过ajax返回文件内容,而是重定向到下载

以下是查看代码:

<script src="../../Scripts/jquery-1.3.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
    $(function() {
        // hide form code here

        // upload to server
        $('#btnUpload').click(function() {
            $.ajax({
                type: 'POST',
                dataType: 'json',
                url: '<%= Url.Action("SaveFile", "Home") %>',
                success: function(fileId) {
                    window.location = '<%= Url.Action("DownloadFile", "Home") %>?fileId=' + fileId;
                },
                error: function() {
                    alert('An error occurred uploading data.');
                }
            });
        });
    });
</script>

<% using (Html.BeginForm()) { %>

    <div>Field 1: <%= Html.TextBox("field1") %></div>

    <div>Field 2: <%= Html.TextBox("field2") %></div>

    <div>Field 3: <%= Html.TextBox("field3") %></div>

    <button id="btnUpload" type="button">Upload</button>

<% } %>

为什么不能只使用非ajax调用呢?我可以,但我想在保存完成后在javaScript函数中做一些其他处理,比如取消对表单的阻止,我在保存之前阻止了表单。好的,所以可以先调用ajax SaveFile。SaveFile将返回true/false。当它返回true时,调用non-ajaxget来获取文件。当我从jquery.ajax调用控制器的SaveFile时,浏览器的下载对话框不会打开。真正的问题是我想在保存过程中阻止UI。我可以很好地保存(提交表单的正常后期处理),但是我无法启动blockUI。我能赶上一个活动(单击按钮或提交处理程序,启动块并显示忙碌指示器,但我无法触发解除阻止。是否有方法从控制器的操作调用jQuery函数以便触发解除阻止。我没有注意到任何可以使用的事件。这就是我尝试通过Ajax调用调用的原因。好的,您仍然可以使用Ajax,但不返回FileConte。)ntResult.Return true/false,如果返回true,则初始化非ajax获取下载文件。Nate,感谢您提供如此详细的示例。我对此表示感谢,也感谢LukLed努力解释您的解决方案。没有深入理解的一点是,第一次调用准备好了要保存的数据,而第二次调用则不需要e下载。在我把头撞到墙上之前,我就去过那里,我对自己说WTF,试图理解,不用担心。很高兴能帮上忙。
[HandleError]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    public JsonResult SaveFile(string field1, string field2, string field3)
    {
        // save the data to the database or where ever
        int savedFileId = 1;

        // return the saved file id to the browser
        return Json(savedFileId);
    }

    public FileContentResult DownloadFile(int fileId)
    {
        // load file content from db or file system
        string fileContents = "field1,field2,field3";

        // convert to byte array
        // use a different encoding if needed
        var encoding = new System.Text.ASCIIEncoding();
        byte[] returnContent = encoding.GetBytes(fileContents);

        return File(returnContent, "application/CSV", "test.csv");
    }

    public ActionResult About()
    {
        return View();
    }
}