尽管没有绑定,Controller仍会使用null值填充对象

时间:2015-09-21 13:05:42

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

我仍然在学习很多关于实体框架及其如何通信的知识,所以这可能很简单,但我似乎无法弄清问题是什么。

要设置场景,我有一个由Visual Studio生成的工作Create函数,我在此函数中设置了如下值:

myObject.Id = Guid.NewGuid().ToString();
myObject.dateCreated = DateTime.Now;

这看起来很棒,而且一切正常。当我尝试编辑记录时出现问题。

我有这个型号:

public class MyObject
{
    public string Id { get; set; }
    public string UserId { get; set; }
    public string Name { get; set;  }
    public DateTime dateCreated { get; set; }
    public Nullable<DateTime> dateModified { get; set; }
    public Boolean aDefault { get; set; }

}

(大部分是自动生成的)这些控制器:

public async Task<ActionResult> Edit(string id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    MyObject myObject = await db.myObjects.FindAsync(id);
    if (myObject == null)
    {
        return HttpNotFound();
    }
    return View(myObject);
}

public async Task<ActionResult> Edit([Bind(Include = "Id,aDefault,Name")] MyObject myObject)
{
    if (ModelState.IsValid)
    {
        myObject.dateModified = DateTime.Now;
        db.Entry(myObject).State = EntityState.Modified;
        await db.SaveChangesAsync(); //db is the generated dbcontext
        return RedirectToAction("Index");
    }
    return View(myObject);
}

并且(仅显示表单上的字段)视图:

@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.Id)

<div class="form-group">
    @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
        @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
    </div>
</div>


<div class="form-group">
    @Html.LabelFor(model => model.aDefault, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        <div class="checkbox">
            @Html.EditorFor(model => model.aDefault)
            @Html.ValidationMessageFor(model => model.aDefault, "", new { @class = "text-danger" })
        </div>
    </div>
</div>

因此,当我运行此代码并转到编辑区域时,我希望它采用Name和默认值,将它们发布到控制器,并且只修改数据库中的相关字段。但是,目前当我运行此代码时,我得到:

  

将datetime2数据类型转换为日期时间数据类型会导致超出范围的值。   声明已经终止。

这让我相信我的dateCreated被设置为null。我通过使它成为Nullable来确认这一点,它不再抛出异常,但当然将数据库中的dateCreated设置为null。

我是否需要将所有属性绑定到视图,类似于在隐藏字段中设置Id的方式?我希望不是因为我想我只需要绑定相关的项目。有没有办法可以排除设置一次不更新的字段?

1 个答案:

答案 0 :(得分:0)

感谢评论以及过去24小时的一些研究,我意识到主要问题是实体框架为我生成的问题。这条线让我头疼最多:

db.Entry(myObject).State = EntityState.Modified;

这会将所有属性设置为已修改,因此将所有值的值设置为null,并且未绑定的所有属性都保留为null。

我可以看到为什么另一个选项(也许更好的做法)可能只是为视图中的必要属性添加另一个ViewModel,但我想在这种情况下,控制器可能更适合实现正在改变的内容。这是我修改后的帖子方法:

public async Task<ActionResult> Edit([Bind(Include = "Id,aDefault,Name")] MyObject myObject)
{
    if (ModelState.IsValid)
    {
        db.MyObjects.Attach(myObject); //MyObjects is the DbSet
        myObject.dateModified = DateTime.Now;
        db.Entry(myObject).Property(o => o.Name).IsModified = true;
        db.Entry(myObject).Property(o => o.aDefault)IsModified = true;
        await db.SaveChangesAsync(); //db is the generated dbcontext
        return RedirectToAction("Index");
    }
    return View(myObject);
}