0

私は現在 asp.net mvc 3 を勉強しており、このチュートリアルに従っています Contoso University

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

私は、モデルの編集が楽観的同時実行で処理されるこの部分にいます

私は次のようなものを使用することによってそれを認識しています

[HttpPost]
public ActionResult Edit(Department department)

編集する部門の ID の非表示フィールドがなくても、モデルは自動的にバインドされ、編集は失敗しません。

しかし、この 1 つのビューで 2 つの隠しフィールドを削除しようとするたびに:

@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; }
    }

隠しフィールドを使用せずに機能させることは可能ですか?

閣下/奥様、あなたの答えは大変役に立ちます。ありがとう++

4

1 に答える 1

2

あなたのアクション署名に基づいてHttpPost、いいえ、これは不可能です。を実行しているため、更新中の行のEditが必要になります。Idアクション メソッド シグネチャで をマッピングしておらずId、その情報を保持する隠しフィールドが存在しないため、id がDepartmentモデルにマッピングされることはありません。その結果、行 ID なしで更新を実行しようとすることになります。

EDIT : アクション シグネチャを so:Edit(int id, Department department)のように変更できますが、手動で をdepartment.Id渡さidれたものに設定する必要があり、モデルが多少ばらばらになっているように見えます。

于 2013-01-31T14:41:02.557 に答える