模型状态 - 你看到的不是你得到的 - 重新审视

时间:2012-05-01 16:55:30

标签: asp.net-mvc-3

由于模型状态,已经有几个关于如何在视图控制器中设置的模型属性不会在视图中显示的很好的讨论。为了进一步讨论,我有一个例子,其中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;
    }
}

Controller(其中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>

情景 - 用户请求页面并查看红色水果列表。 - 用户单击过滤器按钮,后置控制器加载所有水果,用户看到所有三个水果的列表 - 用户再次单击过滤器按钮。现在检查传递给帖子控制器的篮子属性,列表将与用户看到的不匹配。

现在想象一下,您想使用该复选框选择要从篮子中移除的水果。您可以将basket.fruits模型传递给数据访问类中的方法,该方法将删除水果,然后您可以让您的控制器重新加载basket.fruits列表。但它不起作用,因为返回控制器的列表与用户看到的列表不匹配。

通过将以下内容放入Post控制器

,可以破坏此“功能”
ModelState.Clear();

但实际上,我不应该这样做。视图和控制器应该准确地来回传递模型。 ModelState试图在页面加载之间保持View属性,这似乎与MVC哲学不一致,其中状态由数据库管理,而不是视图!

0 个答案:

没有答案