0

簡単だと思われることをしようとしていますが、MVC と規約ベースのプログラミングは初めてです。

AJAX を介して PDF ドキュメントの行を取得する jQuery データテーブルがあります。にfnRowCallbackチェックボックスを追加して、ユーザーが複数のドキュメントを選択して 1 回のダウンロードに結合できるようにしました。チェックボックスをオンにすると、ドキュメント ID が数値の JavaScript 配列に追加され、ファイル名が別の配列に追加されるため、結合すると、結果の PDF のブックマークに使用できます。これら 2 つの変数をコントローラー アクションに送信する方法はありますか? これまでのところ、私ができることはJSON.stringify()変数の1つをビューに配置し、コントローラーで逆シリアル化するフォームの隠しフィールドを使用してコントローラーに送信しますが、2番目の変数を追加しようとすると、それがうまくいきません。もっと簡単な方法があるはずですが、複雑な方法を理解することさえできず、私が読んだすべての記事は 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

あなたの答えは90%正解です、Kroehre。迅速な対応ありがとうございます。唯一の問題は、アプリケーションが使用するコントローラーアクションを認識できないため、ページの読み込みに失敗し、わかりやすいエラーページにリダイレクトされることです。ただし、その解決策は非常に簡単でした。以下にコードを配置します。

ビューdiv構文上の影響はありませんでしたが、何も表示されないプレゼンテーションセマンティクスでコードを汚したと感じたので、sを省略しました。個人的な好みなので、欠落している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 に答える