ASP.Net MVC ModelState / Html.TextBoxポストバックの問題
-
08-07-2019 - |
質問
投稿しようとしているフォームで切り抜ける問題があります。フォームが検証されないシナリオでは、 ModelState.AddModelError()
を呼び出してViewの結果を返すという標準的なルートを取っています。
問題は、HTML。*ヘルパーがレンダリング時に投稿された値を取得することになっていることです。ポストバックアクションのパラメーターリストにテキストフィールドを含めると、テキストフィールドのみがそうなることに気付きました。一部のフォームにはフィールドが多すぎるため、それらをすべてパラメータとしてリストしたくないため、確認する必要があります。
アクションコードは大体次のとおりです。
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditDataDefinition(long? id, string name)
{
var dataDefinition = ...
// do some validation stuff
if (!ModelState.IsValid)
{
// manually set checkbox fields via ViewData seeing as this STILL doesn't work in MC 1.0 :P
// ...
return View(dataDefinition);
}
}
現在、dataDefinition(これはLINQ to SQLエンティティです)にはフィールド MinVolume があり、この行でビューで処理されます:
Minimum: <%= Html.TextBox("MinVolume", null, new { size = 5 })%>
まだ、ModelStateの検証に失敗した後にビューがレンダリングされると、ポストバックメソッドのパラメーターとして含めるまで、投稿した元のページで入力した値は保持されません。文字通り、「問題を解決する」ことができます。これにより:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditDataDefinition(long? id, string name, string minVolume)
何らかの理由で、フィールド値が強制的に保存されます。私のフォームにはそれよりもはるかに多くの値があり、そのフィールドだけにパラメータを追加する必要がないので、これは私には愚かに思えます。
アイデアはありますか
解決
コードは次のようになりますか:
<%= Html.TextBox("MinVolume", null, new { size = 5 })%>
..はデフォルト値paramの null
を持っていますか? null
を Model.MinVolume
に変更すると、値が保持される可能性があります。このように:
<%= Html.TextBox("MinVolume", Model.MinVolume, new { size = 5 })%>
アクションがモデルthoで値 MinVolume
を返すかどうかはわかりません。もしそうなら、上記は動作するはずです。そうでない場合、アクションを少しリファクタリングする必要があるかもしれません。
他のヒント
ああ、私はアプリケーションの設計を改善しました。 問題は、カスタム検証があるために発生します(私も持っています)。 後に追加する必要があります
ModelState.AddModelError()
this
ModelState.SetModelValue("MinVolume", ValueProvider["MinVolume"]);
ビューでは
Mimum:<%=Html.Textbox("MinVolume")%>
それがなぜ機能するのかはまだわかりませんが、私にとってはうまくいきました。
エラー時にModelStateに値を設定するときに使用しているキーは何ですか? TextBoxの値パラメーターを設定するコードは次のようになります。
ダウンロードされたフレームワークコードの関連部分。
>string attemptedValue = (string)htmlHelper.GetModelStateValue(name, typeof(string));
tagBuilder.MergeAttribute("value", attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(name) : valueParameter), isExplicitValue);
試行値が存在するかどうかを見るとわかるように、同じ値が使用可能な場合にのみ使用されます。
パラメータを使用せず、ValueProviderから値を直接取得するアクションがあり、AddModelErrorを使用して検証エラーを示すため、これが機能することを知っています。 TextBoxの値は確実に保持されます。
編集:値を保持するには、何らかの方法でモデルに関連付ける必要があります。これを行う1つの方法は、それらをパラメーターリストに追加することです。もう1つの方法は、UpdateModelを使用することです(ホワイトリストにパラメーター名を含めるか、ホワイトリストなしで)。 3番目の方法は、@ Jeneaの答えのように、モデルにパラメーターを明示的に追加することです。ヘルパーはモデル状態からのみプルするため、値が保持されるためにはヘルパーがそこにいる必要があります。リクエストのフォームプロパティは参照しません。
解決策は次のとおりです:
[Transaction]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditDataDefinition(int id, FormCollection form)
{
T itemToUpdate = repository.Get(id);
UpdateModel(itemToUpdate, form.ToValueProvider());
if (itemToUpdate.IsValid())
{
repository.SaveOrUpdate(itemToUpdate);
return Json(ValidationResultToJson(itemToUpdate.ValidationResults()));
}
repository.DbContext.RollbackTransaction();
return Json(ValidationResultToJson(itemToUpdate.ValidationResults()));
}
がんばって!
別の解決策は、ビューに入力する場合です:
<%var minVolume=Request["MinVolume"]??"";%>
<%=Html.Textbox("MinVolume",minVolume,new {size=5})%>
ASP.NET MVCでポストバックを処理するさまざまな方法については、この記事を参照してください