Asp.net mvc 3模型没有自动绑定?

时间:2013-01-31 14:37:42

标签: asp.net-mvc-3 entity-framework entity-framework-4 entity-framework-4.1

我正在学习asp.net mvc 3,我正在学习这个教程Contoso大学

http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/handling-concurrency-with-the-entity-framework-in-an-asp-net-mvc-application

我正处于使用Optimistic Concurrency

处理模型编辑的部分

我知道通过使用像

这样的东西
[HttpPost]
public ActionResult Edit(Department department)

模型将自动绑定,即使没有要编辑的部门ID的隐藏字段,编辑也不会失败。

但每当我尝试删除这个视图中的两个隐藏字段时:

@model MvcContosoUniversity.Models.Department

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Department</legend>

       @Html.HiddenFor(model => model.DepartmentID) 
         @Html.HiddenFor(model => model.Timestamp)
        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Budget)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Budget)
            @Html.ValidationMessageFor(model => model.Budget)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.StartDate)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.StartDate)
            @Html.ValidationMessageFor(model => model.StartDate)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.InstructorID, "Administrator")
        </div>
        <div class="editor-field">
            @Html.DropDownList("InstructorID", String.Empty)
            @Html.ValidationMessageFor(model => model.InstructorID)
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

我在控制器中出错,这是控制器的代码:

 // GET: /Department/Edit/5

        public ActionResult Edit(int id)
        {
            Department department = db.Departments.Find(id);
            ViewBag.InstructorID = new SelectList(db.Instructors, "InstructorID", "FullName", department.InstructorID);
            return View(department);
        }

        //
        // POST: /Department/Edit/5

        [HttpPost]
        public ActionResult Edit(Department department)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    db.Entry(department).State = EntityState.Modified;
                    db.SaveChanges();
                    return RedirectToAction("Index");
                }
            }
            catch (DbUpdateConcurrencyException ex)
            {
                var entry = ex.Entries.Single();
                //Another option is to put the try-catch inside a function
                try
                {
                    var databaseValues = (Department)entry.GetDatabaseValues().ToObject();
                    var clientValues = (Department)entry.Entity;
                    if (databaseValues.Name != clientValues.Name)
                        ModelState.AddModelError("Name", "Current value: "
                            + databaseValues.Name);
                    if (databaseValues.Budget != clientValues.Budget)
                        ModelState.AddModelError("Budget", "Current value: "
                            + String.Format("{0:c}", databaseValues.Budget));
                    if (databaseValues.StartDate != clientValues.StartDate)
                        ModelState.AddModelError("StartDate", "Current value: "
                            + String.Format("{0:d}", databaseValues.StartDate));
                    if (databaseValues.InstructorID != clientValues.InstructorID)
                        ModelState.AddModelError("InstructorID", "Current value: "
                            + db.Instructors.Find(databaseValues.InstructorID).FullName);
                    ModelState.AddModelError(string.Empty, "The record you attempted to edit "
                        + "was modified by another user after you got the original value. The "
                        + "edit operation was canceled and the current values in the database "
                        + "have been displayed. If you still want to edit this record, click "
                        + "the Save button again. Otherwise click the Back to List hyperlink.");
                    department.Timestamp = databaseValues.Timestamp;
                }

                catch(NullReferenceException e)
                {
                    ModelState.AddModelError("","Error \n "+e.Message);
                }
            }
            catch (DataException)
            {
                //Log the error (add a variable name after Exception)
                ModelState.AddModelError(string.Empty, "Unable to save changes. Try again, and if the problem persists contact your system administrator.");
            }

            ViewBag.InstructorID = new SelectList(db.Instructors, "InstructorID", "FullName", department.InstructorID);
            return View(department);
        }

以下是该模型的代码:

public class Department
    {
        public int DepartmentID { get; set; }

        [Required(ErrorMessage = "Department name is required.")]
        [MaxLength(50)]
        public string Name { get; set; }

        [DisplayFormat(DataFormatString = "{0:c}")]
        [Required(ErrorMessage = "Budget is required.")]
        [Column(TypeName = "money")]
        public decimal? Budget { get; set; }

        [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
        [Required(ErrorMessage = "Start date is required.")]
        public DateTime StartDate { get; set; }

        [Display(Name = "Administrator")]
        public int? InstructorID { get; set; }

        public virtual Instructor Administrator { get; set; }
        public virtual ICollection<Course> Courses { get; set; }

         [Timestamp]
        public Byte[] Timestamp { get; set; }
    }

是否可以在不使用隐藏字段的情况下使其工作?

先生/女士,你的答案会有很大的帮助。谢谢++

1 个答案:

答案 0 :(得分:2)

根据您的HttpPost操作签名,不,这是不可能的。您正在执行Edit,因此需要正在更新的行的Id。由于您未在操作方法签名中映射Id,并且不存在包含该信息的隐藏字段,因此ID将永远不会映射到Department模型。结果是您将尝试执行没有行ID的更新。

编辑:您可以修改自己的操作签名:Edit(int id, Department department),但是您必须手动将department.Id设置为id通过这似乎使模型有点脱节。