强类型视图绑定对象集合而不会被ModelState搞砸

时间:2013-08-30 18:38:26

标签: asp.net-mvc-3

注意:我仍然是ASP.Net MVC的新手,所以我可能采取了错误的方法;不要犹豫。

问题的摘要是,如果我的视图强烈地键入某些模型对象集合(例如,IEnumerable<ModelStateTest.Models.DataObject>),并且我在视图上有多个表单 - 每个模型对象一个在集合中 - 然后发布任何一个表单会导致所有表单反映已编辑的特定对象的值。

我理解为什么它会这样做;如果您进行某些服务器端验证或处理,并且它失败,您不希望丢弃所有用户的更改并恢复到先前存储在数据库中的更改。我不知道的是如何在具有绑定到多个对象的表单的页面上管理此行为。

这是一些演示行为的示例代码。如果单击任何“保存”按钮,则所有三个表单都会反映您保存的表单中的任何字段值。我希望发生;我只希望保存的行反映发布的表单变量。我只是粗略地想到如何实现这一目标,而且我不想巧妙地编码。

模型\ DataObject.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ModelStateTest.Models {
    public class DataObject {
        public string Field1 { get; set; }
        public string Field2 { get; set; }
        public string Field3 { get; set; }
    }
}

控制器\ HomeController.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ModelStateTest.Models;

namespace ModelStateTest.Controllers {
    public class HomeController : Controller {
        public ActionResult Index() {
            return View("Index", new List<DataObject> {
                new DataObject { Field1 = "Obj 1, Field 1", Field2 = "Obj 1, Field 2", Field3 = "Obj 1, Field 3" },
                new DataObject { Field1 = "Obj 2, Field 1", Field2 = "Obj 2, Field 2", Field3 = "Obj 2, Field 3" },
                new DataObject { Field1 = "Obj 3, Field 1", Field2 = "Obj 3, Field 2", Field3 = "Obj 3, Field 3" }
            });
        }

        public ActionResult SaveItem(DataObject obj) {
            return Index();
        }
    }
}

视图\主页\ Index.cshtml:

@model IEnumerable<ModelStateTest.Models.DataObject>

@{
    ViewBag.Title = "Index";
}

@foreach (var obj in Model) {
    using (Html.BeginForm("SaveItem", "Home", FormMethod.Get)) {
        @Html.TextBox("Field1", obj.Field1);
        @Html.TextBox("Field2", obj.Field2);
        @Html.TextBox("Field3", obj.Field3);
        <input type="submit" value="Save" />
    }
}

1 个答案:

答案 0 :(得分:0)

所以这很有效,但很糟糕。我在这里发帖,希望有人有更好的解决方案。如果我这样做,我基本上必须维护两组表单代码。

我在DataObject中添加了一个“主键”字段,然后通过查看Request.QueryString来检查是否正在修改该项目。如果是,我使用HTML Helpers。如果没有,我使用普通的旧输入标签。但我不可能相信这是处理它的最好方法。

<强>模型\ DataObject.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ModelStateTest.Models {
    public class DataObject {
        public int Key { get; set; }
        public string Field1 { get; set; }
        public string Field2 { get; set; }
        public string Field3 { get; set; }
    }
}

<强>控制器\ HomeController.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ModelStateTest.Models;

namespace ModelStateTest.Controllers {
    public class HomeController : Controller {
        public ActionResult Index() {
            return View("Index", new List<DataObject> {
                new DataObject { Key = 1, Field1 = "Obj 1, Field 1", Field2 = "Obj 1, Field 2", Field3 = "Obj 1, Field 3" },
                new DataObject { Key = 2, Field1 = "Obj 2, Field 1", Field2 = "Obj 2, Field 2", Field3 = "Obj 2, Field 3" },
                new DataObject { Key = 3, Field1 = "Obj 3, Field 1", Field2 = "Obj 3, Field 2", Field3 = "Obj 3, Field 3" }
            });
        }

        public ActionResult SaveItem(DataObject obj) {
            return Index();
        }
    }
}

<强>视图\主页\ Index.cshtml:

@model IEnumerable<ModelStateTest.Models.DataObject>

@{
    ViewBag.Title = "Index";
}

@foreach (string name in Request.Form) {
    <pre>@name = @Request.Form[name]</pre>
}

@foreach (var obj in Model) {
    using (Html.BeginForm("SaveItem", "Home", FormMethod.Get)) {
        if (Request.QueryString["Key"] == obj.Key.ToString()) {
            @Html.Hidden("Key", obj.Key);
            @Html.TextBox("Field1", obj.Field1);
            @Html.TextBox("Field2", obj.Field2);
            @Html.TextBox("Field3", obj.Field3);
        } else {
            <input type="hidden" name="Key" value="@obj.Key" />
            <input type="text" name="Field1" value="@obj.Field1" />
            <input type="text" name="Field2" value="@obj.Field2" />
            <input type="text" name="Field3" value="@obj.Field3" />
        }
        <input type="submit" value="Save" />
    }
}