同じことを知りたくてこの質問に出くわしました。以下は、私の状況と私が使用した解決策の詳細な説明です(ここで提供されている他の回答を利用しています)。私はもともと 2 つの別々のメソッド アプローチを使用しようとしましたが、これらのメソッドのメソッド シグネチャが同一になったときに問題が発生しました。
レポート データを表示するページがあります。ページの上部には、いくつかのフィールドを含むフォームがあり、ユーザーは開始日、終了日などのレポート パラメータを指定できます。
私は当初、Get メソッドと Post メソッドを処理する 2 つの別個のメソッドを作成することで、これに取り組みました。post メソッドはブラウザーを get メソッドにリダイレクトします。これにより、指定されたすべてのパラメーターがクエリ文字列に追加され、ブラウザーが入力したデータを再送信するというダイアログをユーザーに表示しなくなります。リフレッシュする場合。注:フォーム要素のメソッド属性を「Get」に設定することでこれを達成できることに後で気付きましたが、理想的にはコントローラーはビューがどのように実装されているかを知っているべきではないと思うので、私の意見ではそれは無関係です。
これら 2 つのメソッドを開発していると、最終的にはメソッド シグネチャが同じになる状況に陥りました。さらに、これら 2 つのメソッドのコードはほぼ同じになったので、それらを 1 つのメソッドにマージし、リクエスト動詞をチェックして、リクエストが「Get」でない場合に少し異なることを実行できるようにすることにしました。私の 2 つの方法の簡単な例を以下に示します。
// this will not compile because the method signatures are the same
public ActionResult MyReport(DateRangeReportItem report)
{
// if there are no validation errors and the required report parameters are completed
if (ModelState.IsValid && report.ParametersAreComplete)
{
// retrieve report data and populate it on the report model
report.Result = GetReportData(report.CreateReportParameters());
}
return View(report);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult MyReport(DateRangeReportItem report)
{
if (ModelState.IsValid && report.ParametersAreComplete)
{
// redirect to the same action so that if the user refreshes the browser it will submit a get request instead of a post request
// this avoids the browser prompting the user with a dialog saying that their data will be resubmitted
return RedirectToAction("MyReport", new { StartDate = report.StartDate, EndDate = report.EndDate });
}
else
{
// there were validation errors, or the report parameters are not yet complete
return View(report);
}
}
モデル オブジェクトを get メソッドのパラメーターとして受け入れるのはなぜですか? その理由は、モデル オブジェクトに既に組み込まれている検証ロジックを利用したかったからです。クエリ文字列ですべてのパラメーターが既に指定されている状態で誰かが私のページに直接移動した場合、先に進んでレポート データを取得し、ページに表示したいと考えています。ただし、クエリ文字列で指定されたパラメーターが無効な場合は、検証エラーもページに表示する必要があります。モデル オブジェクトをパラメーターとして配置することにより、MVC フレームワークは自動的にモデル オブジェクトの入力を試み、追加の作業を行わなくても検証エラーをキャプチャします。
この質問に対して投稿された他の回答を使用して、プロジェクトのベース コントローラー クラスに RequestHttpVerb プロパティを作成しました。
public HttpVerbs RequestHttpVerb
{
get { return (HttpVerbs)Enum.Parse(typeof(HttpVerbs), this.Request.HttpMethod, true); }
}
したがって、最終的に私の統合メソッドは次のようになります。
[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
public ActionResult MyReport(DateRangeReportItem report)
{
// check if there are any validation errors in the model
// and whether all required report parameters have been completed
if (ModelState.IsValid && report.ParametersAreComplete)
{
// this is unnecessary if the form method is set to "Get"
// but within the controller I do not know for sure if that will be the case in the view
if (HttpVerbs.Get != this.RequestHttpVerb)
{
// redirect to the same action so that if the user refreshes the browser it will submit a get request instead of a post request
// this avoids the browser prompting the user with a dialog saying that their data will be resubmitted
return RedirectToAction("MyReport", new { StartDate = report.StartDate, EndDate = report.EndDate });
}
// there were no validation errors and all required report parameters are complete
// retrieve report data and populate that data on the model
report.Result = GetReportData(report.CreateReportParameters());
}
// display the view with the report object
// Any model state errors that occurred while populating the model will result in validation errors being displayed
return View(report);
}
それが問題に対する私の現在の解決策です。リダイレクトを実行する必要があるかどうかを判断するために Request.HttpMethod プロパティを確認する必要はありませんが、問題に対する別の解決策が見つかりませんでした。Get リクエストと Post リクエストを処理するために 2 つの別々のメソッドを保持していれば問題ありませんでしたが、同じメソッド シグネチャがこれを妨げていました。Post アクション ハンドラー メソッドの名前を変更して、メソッド シグネチャの競合を回避し、何らかのメカニズムを使用して、名前を変更したメソッドが "MyReport" アクションを引き続き処理する必要があることを MVC フレームワークに示すことをお勧めしますが、そのようなメカニズムを認識していません。 MVC フレームワークで。