I am refactoring MvcMusicStore code and I'm in the process of updating the StoreManagerController. I have changed the Edit actions to the following:
//
// GET: /StoreManager/Edit/5
public ActionResult Edit(int id)
{
Toy toy = dbStore.Toys.Find(id);
ViewBag.CategoryId = new SelectList(dbStore.Categories, "CategoryId", "Name", toy.CategoryId);
ViewBag.BrandId = new SelectList(dbStore.Brands, "BrandId", "Name", toy.BrandId);
return View(toy);
}
//
// POST: /StoreManager/Edit/5
[HttpPost]
public ActionResult Edit(Toy toy)
{
if (ModelState.IsValid)
{
dbStore.Entry(toy).State = EntityState.Modified;
dbStore.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CategoryId = new SelectList(dbStore.Categories, "CategoryId", "Name", toy.CategoryId);
ViewBag.BrandId = new SelectList(dbStore.Brands, "BrandId", "Name", toy.BrandId);
return View(toy);
}
While testing, when I click the Edit
action, the view displays fine and setting a breakpoint in the Edit(int id)
method shows that the ToyId
is 1. However, after I make a change and click Save, the Toy
object being passed through the method ActionResult Edit(Toy toy)
has the incorrect ToyId
equal to 0.
Where is this modification occurring, or is there a copy of toy
being passed back from the view and it is not correctly copying across the ToyId?
Update: Added Post of Edit View
@model Store.Models.Toy
@{
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>Toy</legend>
@Html.HiddenFor(model => model.ToyId)
<div class="editor-label">
@Html.LabelFor(model => model.CategoryId, "Category")
</div>
<div class="editor-field">
@Html.DropDownList("CategoryId", String.Empty)
@Html.ValidationMessageFor(model => model.CategoryId)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.BrandId, "Brand")
</div>
<div class="editor-field">
@Html.DropDownList("BrandId", String.Empty)
@Html.ValidationMessageFor(model => model.BrandId)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Title)
@Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">开发者_如何学JAVA
@Html.LabelFor(model => model.Price)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Price)
@Html.ValidationMessageFor(model => model.Price)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.PictureUrl)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.PictureUrl)
@Html.ValidationMessageFor(model => model.PictureUrl)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
Toy Class
[Bind(Exclude = "ToyId")]
public class Toy
{
[ScaffoldColumn(false)]
public int ToyId { get; set; }
// ... other stuff here
}
It's because of
[Bind(Exclude = "ToyId")]
So the ToyID property is literally being ignored in the bind operation and the hidden value is not being used.
You can simply remove this from the class so that ToyId
gets correctly bound from the POST operation; or, you can manually bind it in the controller method by copying the id
route value to the Toy
's ToyId
property (or add a method parameter called id
to have it bound automatically).
There are some potential issues with allowing binding of ID properties etc, however, and this other SO provides a window into this: ASP.NET MVC - Alternative for [Bind(Exclude = "Id")]
精彩评论