0

我正在尝试做一些看起来应该很容易的事情,但我是 MVC 和基于约定的编程的新手。

我有一个 jQuery 数据表,它通过 AJAX 获取 PDF 文档的行。在 中fnRowCallback,我添加了复选框,以便用户可以选择多个文档进行组合以进行单个下载。当复选框被选中时,文档 ID 被添加到一个 JavaScript 数字数组中,文件名被添加到另一个数组中,以便在组合时,它们可以用于生成的 PDF 中的书签。有没有办法将这两个变量发送到控制器动作?到目前为止,我所能做的就是JSON.stringify()其中一个变量并使用我放在视图中的表单中的隐藏字段将其发送到控制器,然后在控制器中对其进行反序列化,但是当我尝试添加第二个变量时,我把它搞砸了。必须有一种更简单的方法,但我什至无法弄清楚复杂的方法,我读过的所有文章都使用 AJAX。不过,我不能使用 AJAX,因为您不能在响应中发回二进制文件。

JavaScript:

var aiSelectedPDFs = new Array();
var aiSelectedDocumentIDs = new Array();

$('#imgDownload').click(function () {
    $('#selectedPDFs').val(JSON.stringify(aiSelectedPDFs));
    $('#selectedDocumentIDs').val(JSON.stringify(aiSelectedDocumentIDs));
    $('#DownloadSelectedPdfs').submit();
});

看法:

<img id="imgDownload" src="@(Url.RootUrl())Content/images/icons/pdf.gif" 
    alt="Download selected documents" title="Download selected documents" />
@using (Html.BeginForm("DownloadSelectedPdfs", "Controller", FormMethod.Post, 
    new { id = "DownloadSelectedPdfs" }))
{
    <input type="hidden" id="selectedPdfs" name="jsonSelectedPdfs"/>
    <input type="hidden" id="selectedDocumentIDs" name="jsonSelectedDocumentIDs"/>
}

控制器:

    [HttpPost]
    public ActionResult DownloadSelectedPdfs(string jsonSelectedDocumentIDs)
    {
        var selectedDocumentIDs = new JavaScriptSerializer().Deserialize<int[]>(
            jsonSelectedDocumentIDs);
        var invoices = new Dictionary<string, byte[]>();

        foreach (int documentID in selectedDocumentIDs)
        {
            invoices.Add(documentID.ToString(), 
                _documentService.GetDocument(documentID));
        }

        return new FileContentResult(PdfMerger.MergeFiles(invoices), 
            "application/pdf");
    }
4

2 回答 2

1

Kroehre,你的答案 90% 正确。谢谢你这么快的回复。唯一的问题是应用程序无法确定要使用的控制器操作,因此页面无法加载,我被重定向到友好的错误页面。不过,解决方案非常简单,我将把代码放在下面。

查看(我省略了divs ,因为我觉得它们用表示语义弄脏了代码,其中没有任何内容可以显示,尽管它们没有语法影响。只是个人喜好,所以不是丢失的 10% 的一部分。;-)):

<img id="imgDownload" src="@(Url.RootUrl())Content/images/icons/pdf.gif" 
    alt="Download selected documents" title="Download selected documents" />
@using (Html.BeginForm("DownloadSelectedPdfs", "Controller", FormMethod.Post, 
    new { id = "DownloadSelectedPdfs" })) { }

脚本(创建了类似的多个隐藏输入,但命名为具有属性的相同对象):

var aiSelectedPDFs = new Array();
var aiSelectedDocumentIDs = new Array();

$('#imgDownload').click(function () {
    var form = $('#DownloadSelectedPdfs');
    form.html('');
    for (var i = 0; i < aiSelectedPDFs.length; i++) {
        form.append('<input type="hidden" name="selectedPDFs[' + i + '].RefNumber" 
            value="' + aiSelectedPDFs[i] + '" />');
        form.append('<input type="hidden" name="selectedPDFs[' + i + '].DocumentID" 
            value="' + aiSelectedDocumentIDs[i] + '" />');
    }
    form.submit();
});

控制器(添加了新类来处理多个相关的 javascript 变量):

public class PDFViewModel
{
    public int RefNumber { get; set; }
    public int DocumentID { get; set; }
}

[HttpPost]
public ActionResult DownloadSelectedPdfs(List<PDFViewModel> selectedPDFs)
{
    var pdfs = new Dictionary<string, byte[]>();

    foreach (var selectedPDF in selectedPDFs)
    {
        var document = _documentService.GetDocument(selectedPDF.DocumentID);
        var tabName = string.Format("pdf_{0}", selectedPDF.RefNumber);
        pdfs.Add(tabName, document);
    }

    return new FileContentResult(PdfMerger.MergeFiles(pdfs), "application/pdf");
}
于 2012-05-04T15:28:37.800 回答
0

通过为每个值指定数组名称和索引,可以通过表单传输数组。我修改了你的代码:

查看(用容器替换隐藏的输入):

<img id="imgDownload" src="@(Url.RootUrl())Content/images/icons/pdf.gif" 
    alt="Download selected documents" title="Download selected documents" />
@using (Html.BeginForm("DownloadSelectedPdfs", "Controller", FormMethod.Post, 
    new { id = "DownloadSelectedPdfs" }))
{
    <div id="pdfs"></div>
    <div id="docs"></div>
}

脚本(为数组中的项目添加/填充隐藏输入,而不是使用字符串化):

var aiSelectedPDFs = new Array();
  var aiSelectedDocumentIDs = new Array();

  function createInputs(container, name, values){
    $(container).html('');
    for(var i = 0; i<values.length; i++){
      $(container).append('<input type="hidden" name="' + name + '[' + i + ']" value="' + values[i] + '" />');
    }    
  }

  $('#imgDownload').click(function () {
    createInputs('#pdfs', 'selectedPdfs', aiSelectedPDFs);
    createInputs('#docs', 'selectedDocumentIDs', aiSelectedDocumentIDs);
    $('#DownloadSelectedPdfs').submit();
  });

控制器(更新输入参数以与发布的数组对齐,利用 MVC3 的内置模型绑定器):

[HttpPost]
    public ActionResult DownloadSelectedPdfs(List<int> selectedPdfs, List<int> selectedDocumentIDs)
    {
        var invoices = new Dictionary<string, byte[]>();

        foreach (int documentID in selectedDocumentIDs)
        {
            invoices.Add(documentID.ToString(), 
                _documentService.GetInvoice(documentID));
        }

        return new FileContentResult(PdfMerger.MergeFiles(invoices), 
            "application/pdf");
    }

*注意 - 我使用List<int>参数而不是int[]因为类型必须能够在实例化后添加元素,以便模型绑定器在读取发布的值时正常运行。

于 2012-05-03T22:45:05.533 回答