EF 6 ModelState.IsValid在Id上是假的

时间:2015-12-10 23:09:43

标签: c# asp.net-mvc entity-framework

我有一个Code First项目MVC 5.简化我有以下模型:

public class Person
{
    public int Id { get; set; }
    public string ItemCode { get; set; }
    public string Description { get; set; }
}

在我看来,我有一个带有文本框的表:

@model IList<ItemApp.Models.Item>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

@using(Html.BeginForm("Process", "Items", FormMethod.Post))
{
    @Html.AntiForgeryToken()

    <button type="button" class="btn btn-primary" id="btnAddRow">AddRow</button>
    <input type="submit" class="btn btn-success" value="process"/>
<table class="table">
    <tr>
        <th>
            ItemCode
        </th>
        <th>
            Description
        </th>
    </tr>

        @for (int i = 0; i < Model.Count(); i++ )
        {
            <tr>
                <td>
                    <input type="hidden" value="@i" name="Index" />

                    @Html.TextBoxFor(item => item[i].ItemCode)
                </td>
                <td>
                    @Html.TextBoxFor(item => item[i].Description)
                </td>

            </tr>
        }
    <tr>
        <td>
            <input type="hidden" value="4" name="Index" />
            <input type="hidden" name="[4].Id" />
            <input type="text" name="[4].ItemCode" />
        </td>
        <td>
            <input type="text" name="[4].Description" />
        </td>
    </tr>

</table>

}

正如您在我看来所看到的,我添加了一行。运行te项目时,前3行通过数据库填充。当我在最后一行输入值并提交表单时,您可以看到我的操作收到Item对象列表(Count = 4)。我的流程操作如下所示:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Process(List<Item> items)
{
    if(ModelState.IsValid)
    {
        foreach(var item in items)
        {            
            if(item.Id != 0)
            {
                db.Entry(item).State = System.Data.Entity.EntityState.Modified;
            }
            else
            {
                db.Items.Add(item);
            }

            db.SaveChanges();
        }

        return RedirectToAction("Index");
    }

    return RedirectToAction("Index");
}

问题是我的ModelState.IsValid返回false。这是因为最后一个(新输入的)行的Id = 0。 我想要的是提交表单,更新数据库中已有的所有项目并添加一个新项目。

1 个答案:

答案 0 :(得分:2)

您的ModelState无效,因为Id=0(零是int的有效值)无效,因为您为第4项回发了null。您需要将视图更改为

<input type="hidden" name="[4].Id" value="0"/>

所以它回发Id=0(或者您可以简单地省略该元素,并且在您提交表单时值将为0,因为这是int的默认值)

但是,由于您没有为每个现有项目的Id属性生成表单控件,因此这些属性也会Id=0,这意味着您将再次将现有项添加到数据库中,不更新它们。在循环内你还需要

@Html.HiddenFor(item => item[i].Id)

但是,您的代码不够灵活,只有3个现有项目才能使用,并且只允许您添加一个新项目。建议您查看答案herehere,以动态(和删除)集合中的项目。