【问题标题】:Pass JavaScript/JSON array to MVC 'GET' Method将 JavaScript/JSON 数组传递给 MVC 'GET' 方法
【发布时间】:2012-02-25 04:56:22
【问题描述】:

我正在尝试将 Guid 的数组/IEnumerable 传递给 MVC 'GET' 方法,如下所示:

[HttpGet]
public ActionResult ZipResults(IEnumerable<Guid> ids)
{
    using(var zip = new Zip())
    {
        foreach(var id in ids)
        {
            var stream = GetDataStream(id);
            zip.AddEntry("filename.txt", stream);
        }
    }

    var outputStream = new MemoryStream();
    zip.Save(outputStream);

    return FileStreamResult(outputStream, "application/octet-stream"){
        FileDownloadName = "Results.zip" };
}

我的 javascript 看起来像这样:

$('the-button').click(function(){

    // 1. Get the guids from a table and add to javascript array (works fine)
    // 2. Grey-out screen and show processing indicator (works fine)

    // 3. This is how I'm calling the "ZipResults" action:
    $.ajax({
        url: '@Url.Action("ZipResults", "TheController")',
        type: 'GET',
        data: $.toJSON({ ids: _ids }),
        dataType: 'json',
        contentType: 'application/json;charset=utf-8',
        traditional: true,
        success: function(){
            // Undo the grey-out, and remove processing indicator
        },
        error: function(){
        }
    });
});

我的期望是这将在浏览器上弹出下载对话框。实际上,传递给控制器​​的 javascript 数组为空(在服务器端,它在客户端正常工作)。此外,这适用于“POST”,但是,以这种方式使用的“POST”方法不会强制下载对话框...

欢迎提出建议 :)

【问题讨论】:

    标签: c# jquery asp.net .net asp.net-mvc-3


    【解决方案1】:

    您应该避免使用 GET 发送 JSON 请求。试试这样:

    var _ids = [ 
        'e2845bd4-9b3c-4342-bdd5-caa992450cb9', 
        '566ddb9d-4337-4ed7-b1b3-51ff227ca96c',
        '25bc7095-a12b-4b30-aabe-1ee0ac199594'
    ];
    
    $.ajax({
        url: '@Url.Action("ZipResults", "TheController")',
        type: 'GET',
        data: { ids: _ids },
        dataType: 'json',
        traditional: true,
        success: function() {
            // Undo the grey-out, and remove processing indicator
        },
        error: function() {
    
        }
    });
    

    话虽如此,我看到您正在调用一些控制器操作,该操作返回要下载的文件流。您根本不应该使用 AJAX 来执行此操作。这样做的原因是,在您的成功回调中,您将获得 ZIP 文件的内容,但您无能为力。您无法将其保存到客户端计算机,您无法提示用户选择保存位置,您几乎已经破产了。

    因此,如果您想下载文件,则无需 AJAX 调用。你可以使用一个简单的锚:

    @Html.ActionLink("download zip", "ZipResults", "TheController", null, new { id = "download" })
    

    然后:

    $(function() {
        $('#download').click(function() {
            var _ids = [ 
                'e2845bd4-9b3c-4342-bdd5-caa992450cb9', 
                '566ddb9d-4337-4ed7-b1b3-51ff227ca96c',
                '25bc7095-a12b-4b30-aabe-1ee0ac199594'
            ];
    
            var url = this.href;
            for (var i = 0; i < _ids.length; i++) {
                if (url.indexOf('?') > 0) {
                    url += '&ids=' + encodeURIComponent(_ids[i]);
                } else {
                    url += '?ids=' + encodeURIComponent(_ids[i]);
                }
            }
    
            window.location.href = url;
    
            return false;
        });
    });
    

    【讨论】:

    • @ErOx,绝对。如果要下载文件,请不要使用任何 AJAX。
    【解决方案2】:

    问题是 GET 没有获得请求正文。我怀疑如果您查看客户端发出的请求,您会发现它正试图将一个可枚举推到查询字符串中......

    发布 -> 重定向似乎是这里最好的做法。

    【讨论】:

    • 我之前尝试过发布 -> 重定向,但随后将流传递给 RedirectToAction 给了我错误:“此流不支持超时。”
    • 是的。要使用 GET 执行此操作,我认为您需要将数据作为查询参数而不是请求正文发送,然后在服务器端处理查询参数。
    猜你喜欢
    • 2013-01-15
    • 1970-01-01
    • 2011-06-23
    • 2021-08-12
    • 2020-11-25
    • 1970-01-01
    • 1970-01-01
    • 2012-06-06
    • 1970-01-01
    相关资源
    最近更新 更多