3

ASP.Net MVC で、"id" をアクション パラメーターとして渡し、"id" 非表示のフォーム要素を渡すという、非常に奇妙な状況に遭遇しました。「id」パラメーターを持つアクションがあります。この id 値はプロジェクトを表します。渡されたプロジェクトに従業員を割り当てるためのデータ入力フォームを作成するコントローラーアクションがあります (管理者が渡されたプロジェクトに割り当てられる従業員を選択するドロップダウンリストを作成します)。従業員をプロジェクトに割り当てることにより、ProjectEmployee レコード (プロジェクト ID、従業員 ID、およびデータベースの ID 列である組み合わせを表す ID) を作成します。ID 列 (「id」という名前) も非表示のフォーム要素です。プロジェクト/従業員の割り当てを後で編集できるようにする必要があるため、これが必要です。

とにかく、プロジェクトへの新しい従業員の割り当てを作成するとき、プロジェクト ID (アクションに渡される「id」) が「id」隠しフォーム要素に適用されます。

117 をアクションに渡します。117 は projectId です。0は新しいプロジェクト/従業員の割り当てを表すため、0である必要がある「id」隠しフィールドに設定されています。

モデルを見る

id  - unique id that represents the Project/Employee combination
projectId - the "Id" being passed to action
EmployeeId - what the admin is selecting from drop down
rate
startdate
endDate
...

データ入力フォーム

@Html.HiddenFor(m => m.Id) 
@Html.HiddenFor(m => m.ProjectId)
...
Id: @Model.Id <br />
ProjectId: @Model.ProjectId<br />

したがって、 @Html.HiddenFor(m => m.Id) は非表示のフォーム要素を値 117 でレンダリングします。 @Model.Id は 0 を UI にレンダリングします。コードをステップ実行すると、Id プロパティの値が 0 であることが視覚的にわかります。

このバグは本番環境に移行したため、データベーステーブルに新しいレコードを作成する代わりに、「Id」プロパティが誤って設定されているため、実際には既存のレコードを更新しているため、データがめちゃくちゃになってしまいます。 0 (新しいレコードを表す) から 117 (projectId) までであり、別のレコードを更新しています。

4

2 に答える 2

7

HiddenFor がワイヤを交差させて 117 の値を取得するのはなぜですか?

それは設計によるものです。TextBoxFor や HiddenFor などのすべての HTML ヘルパーは、バインド時に最初に ModelState の値を使用し、次にモデルの値を使用します。コントローラーのアクションは次のようになると思います。

public ActionResult Foo(int id)
{
    SomeModel model = ...
    // At this stage model.Id = 0
    return View(model);
}

問題は、デフォルトのモデル バインダーがid、ヘルパーによって使用されるキーを使用して ModelState に値を追加し、モデル プロパティの値が無視されることです。これはバグではありません。これが HTML ヘルパーの設計方法です。最初は知らないと少し混乱しますが、この動作に慣れると、二度と罠にはまることはありません。

この問題を解決する 1 つの可能性は、ModelState からこの値を削除することです。

public ActionResult Foo(int id)
{
    ModelState.Remove("id");
    SomeModel model = ...
    // At this stage model.Id = 0
    return View(model);
}

またはId、モデル内のプロパティの名前を別の名前に変更して、競合を回避します。

于 2012-06-25T14:18:29.373 に答える