モデルの状態が原因で、フォーム ポスト コントローラーで設定されたモデル プロパティがどのようにビューに表示されないかについて、すでにいくつかの良い議論があります。議論をさらに進めるために、モデルの状態が原因で、VIEW 内のアイテムが更新されてもモデルが更新されない例があります。そうです、ユーザーに表示されるものは、投稿で返されるモデル プロパティと一致しません!
リストを持つモデルがあるとします
public class FruitBasket {
public string OwnersName { get; set; }
public IEnumerable<Fruit> Fruits { get; set; }
public string FruitColor { get; set; }
public FruitBasket() {
this.OwnersName = "Bob";
this.FruitColor = "Red";
}
}
public class Fruit {
public string Name { get; set; }
public string Color { get; set; }
}
データ アクセス クラスには、色に基づいて果物のリストを取得するメソッドがあります。
データアクセスコード
public IEnumerable<Fruit> GetFruits(string color) {
if (color == "Red") {
List<Fruit> fruits = new List<Fruit> {
new Fruit { Name = "Apple", Color = "Red" },
new Fruit { Name = "Grape", Color = "Red" }
};
return fruits;
} else {
List<Fruit> fruits = new List<Fruit> {
new Fruit { Name = "Banana", Color = "Yellow"},
new Fruit { Name = "Apple", Color = "Red" },
new Fruit { Name = "Grape", Color = "Red" }
};
return fruits;
}
}
コントローラー (db はデータ アクセス クラス)
public ActionResult FruitBasket() {
FruitBasket basket = new FruitBasket();
basket.Fruits = db.GetFruits("Red");
return View(basket);
}
[HttpPost]
public ActionResult FruitBasket(FruitBasket basket) {
basket.Fruits = db.GetFruits("All");
return View(basket);
}
意見
@model GEWeb.Models.FruitBasket
<!DOCTYPE html>
<html>
<head>
<title>FruitBasket</title>
</head>
<body>
@using (Html.BeginForm()) {
<p>@Html.DisplayFor(model => Model.OwnersName)</p>
<table>
@Html.EditorFor(model => model.Fruits)
</table>
<input type="submit" value="filter" />
}
</body>
</html>
エディター テンプレート (editorfor のテンプレートは views/shared/EditorTemplates にあります) ポストバック時にモデルにリスト データが入力されるように、hiddenfor ヘルパーが含まれています。
@model GEWeb.Models.Fruit
<tr>
<td>
@Html.DisplayFor(model => model.Name)
@Html.HiddenFor(model => model.Name)
</td>
<td>
@Html.DisplayFor(model => model.Color)
@Html.HiddenFor(model => model.Color)
</td>
<td>
@Html.CheckBoxFor(model => model.Remove)
</td>
</tr>
シナリオ - ユーザーがページをリクエストすると、赤い果物のリストが表示されます。- ユーザーがフィルター ボタンをクリックすると、ポスト コントローラーがすべての果物をロードし、ユーザーに 3 つの果物すべてのリストが表示されます。 - ユーザーがもう一度フィルター ボタンをクリックします。ポスト コントローラーに渡されたバスケットのプロパティを調べると、リストはユーザーが見たものと一致しません。
このチェックボックスを使用して、バスケットから削除する果物を選択するとします。果物を削除するデータ アクセス クラスのメソッドに、basket.fruits モデルを渡すことができます。その後、コントローラーに、basket.fruits リストをリロードさせることができます。しかし、コントローラーに返されたリストがユーザーに表示されているものと一致しないため、機能しません。
この「機能」は、以下を Post コントローラーに入れることで覆すことができます。
ModelState.Clear();
しかし、実際には、そうする必要はありません。ビューとコントローラーは、モデルを正確にやり取りする必要があります。ModelState は、ページの読み込み間でビューのプロパティを永続化しようとする試みであり、ビューではなくデータベースによって状態が管理される MVC の哲学と一致していないようです!