2

私は MVC が初めてで、問題が発生しています。ユーザーがアイテムを選択し、ボタンをクリックしてそのアイテムに関するレポートを表示できるビューがあります。レポートは、モデルが初期化されることを期待する MVC ビューでもあります。モデルを初期化し、レポート ビューを呼び出すコントローラー アクション メソッドがあります。

したがって、私のビューは、モデルを初期化し、レポート ビューを呼び出すレポート コントローラーを呼び出す必要があります。レポート コントローラーへの呼び出しは、JavaScript 関数から行う必要があります。

最後に、元のビューを残したまま、レポートを新しいウィンドウに表示したいと考えています。

window.open を使用してレポート ビューを直接呼び出すことができますが、それではレポート初期化子がスキップされ、モデルにアクセスしようとするとレポート ビューがクラッシュします。

window.open を使用してコントローラーを呼び出す方法はありますか? モデルが null の場合、レポート ビューからレポート コントローラーを呼び出すことはできますか? 最初のビューで JavaScript 関数からレポート コントローラーを呼び出すことはできますか?

または、これをどのように処理することをお勧めしますか? ご協力いただきありがとうございます!

URW

疑似コードは次のとおりです。

以下は、私が取り組んでいるビューのコードです。検索フォームです。ユーザーは、フォームの上部にある値を入力して (または入力せずに)、検索をクリックできます。フォームが再表示され、検索フォームの下に検索結果が表示されます。見つかったアイテムのリストの下には、2 つのボタンがあります。1 つは ShowReport 関数を呼び出すボタンで、もう 1 つはウィザードを呼び出すボタンです。2 つのボタンは、両方とも送信する必要があるため、別々のフォームにあります。少なくとも今の私にはそう見えます。フォームが 2 つあることが問題である場合は、変更できます。

// This is the function that should call the controller to show the report
function ShowReport() 
{

    if (ReportID != null && ReportID > 0) 
    {     
      // I need to call report controller passing ReportID
    }
    else 
    { 
      alert("The Report ID is not valid. Please select a different itemand try again.");
      return; 
    }
}

この関数は、ユーザーが行の先頭にあるラジオ ボタンをクリックしてリスト内の項目を選択するたびに、reportID を保存します。また、選択した項目に応じて、[レポートの表示] および [ウィザードの実行] ボタンを有効または無効にします。リスト内のすべての項目でレポートを利用できるわけではないため、この関数は、現在の選択項目でレポートが利用できるかどうかを確認し、レポートが利用できる場合は [レポートを表示] ボタンを有効にします。

function activateStart(annualWaterReportId) {

    // store the ReportID for this ID in a global 
    // in case the user wants to see the Full report
    ReportID = reportId;

    document.getElementById("startButton").disabled = false;
    if (ReportId > 0) {
        document.getElementById("viewReport").disabled = false;
    } else {
        document.getElementById("viewReport").disabled = true;
    }
}

この関数は、ユーザーが項目を選択して [RunWizard] ボタンをクリックすると、レポート ウィザードを開始します。

function startAction() {

var elements = document.getElementsByName("Select");
    var id = null;
    for (var i = 0; i < elements.length; i++) {
        if (elements[i].checked) {
            id = elements[i].value;
            break;
        }
    }
    if (id != null) {
        document.getElementById("IDList").value = id;
        document.forms["runWizard"].submit();
    }
    else {
        alert("You must first select an item before pressing the Start Wizard button. " );
    }
}

次のフォームには、ユーザーが何かを入力または選択し、検索フィールドの下にある [検索] をクリックすると、検索パラメーターになる 3 つのフィールドが表示されます。

@using ((Html.BeginForm("Index", "Search", FormMethod.Post, new { onsubmit = "showLoadMask('Searching...')" })))
{
<table class="searchTable">
    <tr>
        <td>
            <div>
                Name:</div>
            <input name="searchName" type="text" value="@ViewBag.searchName" />
        </td>
        <td>
            <div>
                ID Number:</div>
            <input name="searchID" type="text" value="@ViewBag.searchID"/>
        </td>
        <td>
            <div>
                Year:</div>
            <input name="searchYear" type="text" value="@ViewBag.searchYear"/>
        </td>
</tr>
    <tr>
        <td colspan="4">
            <input type="submit" class="smallButton" value="search" />
        </td>
    </tr>
</table>

}

次に、ユーザーが上の [検索] をクリックしたときに見つかったアイテムのリストが表示されます。各行の前にはラジオ ボタンがあり、ユーザーはリストの下にある 2 つのボタンのいずれかをクリックする前に行を選択するために使用されます。

<table style="width: 100%" id="searchResults">
<thead>
    <tr>
        <th>
            Select Person
        </th>
        <th>
            Name
        </th>
        <th>
            City
        </th>
        <th>
            State
        </th>
        <th>
            Zip Code
        </th>
    </tr>
</thead>
<tbody>
@foreach (var searchVM in Model)
        {
            <tr>
                <td>
                    <input type="radio" name="Select" value="@searchVM.Number" onclick="activateStart(@searchVM.YearID) " />
                </td>
                <td>@searchVM.Number
                </td>
                <td>@searchVM.Name
                <td>@searchVM.City
                </td>
                <td>@searchVM.StateID
                </td>
                <td>@searchVM.PostalCode
                </td>
            </tr>
        }
</tbody>

検索結果の下には重要な 2 つのボタンがあります。1 つはウィザードを表示するためのもので、もう 1 つはレポートを表示するためのものです。このフォームは、ユーザーが上記のリストで項目を選択した後にウィザードにアクセスできるようにするためだけに存在します。

<form id="runWizard" method="post" action="@ViewBag.wizardAction">
<input type="button" value="Start Wizard disabled id="startButton" onclick="startAction()" />
<input type="hidden" name="pageAction" id="pageAction" value="NEXT_ACTION" />
<input type="hidden" name="currentPage" value="3" />

「レポートの表示」ボタンに使用するこのフォームを追加して、ボタンがクリックされたときの動作をより適切に制御できるようにしました。

@using (Html.BeginForm("CallFullReport", "Search", FormMethod.Post, new Dictionary<string, object>{"ReportID", }))
{
// Clicking this button should bring up the report in a new window, while leaving the current window as is.
<input type="submit" value="View Full Report" disabled id="viewReport" onclick="showReport()" />
<input type="hidden" id="ReportID" name="ReportID" value="-1"/>
}

呼び出したいコントローラーは別の dll にあります。ソース コードは HomeController.cs というファイルにあります。コントローラーは次のようになります。

public ActionResult FullReport(int reportID) {
        ReportModel reportModel = null;
        try {
            reportModel = _db.Reports.Find(reportID);
        }
        catch (Exception) {
                // gen up an error message
        }

        return View(reportModel);
    }

最後に、コントローラーが呼び出すビューがあります。コントローラーによって読み込まれた reportModel のデータを使用して、レポートを表示します。意味のあるものを示すことができるように、コードを最小限に抑えました。

<table style="width: 100%">
foreach (Var item in ReportModel)
{
 <tr>
     <td class="tableLabel base">Name: </td>
     <td class="tableData base">@Item.Name</td>
 </tr>
 <tr>
     <td class="lineSpacer">&nbsp;</td></tr>
 <tr>
     <td class="tableLabel base">Address: </td>
     <td class="tableData base">@Item.Street1</td>
 </tr>
 @if (Item.Street2 != null && Item.Street2 != "") 
 {
  <tr>
    <td>&nbsp;</td>
    <td>@Item.Street2</td>
  </tr>
  }
  <tr>
     td>&nbsp;</td>
     <td>@Item.City, @Item.StateID @Item.PostalCode</td>
  </tr>
  <tr><td>&nbsp;</td></tr>
  <tr><td class="tableLabel base">Phones:</td><td class="tableData base">@(new HtmlString(phones))</td></tr>
  <tr><td class="tableLabel base">Email:</td><td class="tableData base"><a href="mailto:@Item.Email">@Item.Email</a></td></tr>
}
</table>

それが私が持っているすべての疑似コードです。私はこのすべてのコードを継承しており、MVC とそれに付随するすべてのことは初めてです。追加情報を提供できるかどうかお知らせください。

ありがとうございます

4

1 に答える 1

2

投稿するコードが非常に多いため、いくつかの一般的な提案しか提供できません。うまくいけば、彼らはあなたの問題を解決するのに役立ちます.

まず、新しいウィンドウを開く場合は、クライアント側で行う必要があります。サーバーから新しいウィンドウを返すことはできません。ユースケースでこれについて言及していないことは知っていますが、注意することが重要です。

レポート ビューのモデルにデータを入力する必要がある場合は、Ajax を使用してモデルを呼び出し、ビューにデータを入力するために必要なデータを渡すのが最も簡単な場合があります。以下は、Molle 博士から借用した jQuery の例ですhttps://stackoverflow.com/a/3825419/1165998

レポートの読み込みを呼び出すボタンに一意の ID を指定します: loadReport

$(document).ready(function () { 
    $('#loadReport').on('click', function (){
        $.post(url, { ReportId: reportId },  function (data) {
            var win=window.open('about:blank');
            with(win.document)
            {
                open();
                write(data);
                close();
            }
        });
    });
});

どちらの場合も新しいブラウザー ウィンドウにプッシュする必要があるため、このデータを入力するために Html.BeginForm を廃止できると思います。CallFullReport セクションを削除し、レポートを読み込むためのボタンを 1 つだけにします (loadReport という一意の ID を持つボタン)。

于 2013-05-29T21:22:21.257 に答える