0

我有 Action 方法和 View 用于编辑某些项目的属性。

    [HttpPost]
    [ValidateAntiForgeryToken]
    [Authorize(Roles = "Admin")]
    public async Task<ActionResult> Edit(Item item)
    {
        if (ModelState.IsValid)
        {
            db.Entry(item).State = EntityState.Modified;

            await db.SaveChangesAsync();
            return RedirectToAction("Index");
        }
        ViewBag.CatagorieId = new SelectList(db.Catagories, "ID", "Name", item.CatagorieId);
        return View(item);
    }    

@model OpenOrderFramework.Models.Item
@using OpenOrderFramework.Extensions
@{
    ViewBag.Title = "edit";
}

<h2>Editing</h2>


@using (Html.BeginForm())
{

    <div class="form-horizontal">
        <h4>The car</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @Html.HiddenFor(model => model.ID)
         <-- etc -->

但是当我提交表单时出现错误

存储更新、插入或删除语句影响了意外数量的行 (0)。

我发现即使项目的真实 ID 不同,发布的项目的操作方法 ID 也始终为 0。 在此处输入图像描述 为什么会这样?

GET 动作方法:

    // GET: Items/Edit/5
     [Authorize(Roles = "Admin")]
    public async Task<ActionResult> Edit(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Item item = await db.Items.FindAsync(id);
        if (item == null)
        {
            return HttpNotFound();
        }
        ViewBag.CatagorieId = new SelectList(db.Catagories, "ID", "Name", item.CatagorieId);
        return View(item);
    }
4

1 回答 1

1

当您发布表单时,对 HttpPost 操作方法的 http 调用是一个完全独立的 Http 请求,并且实体框架无法跟踪该实体。

正如 Darin 在评论中提到的,在 UI 层中混合实体类并不是一个好主意。这使得它耦合非常紧密。

您应该使用的是为您的视图创建和使用视图模型。视图模型只是特定于视图的 POCO 类。

public class ItemViewModel
{
  public int Id {set;get;}
  public string Name {set;get;}
  public List<SelectListItem> Categories { set;get;}
  public int SelectedCategory {set;get;}
}

在您的 GET 操作中,从数据库中读取实体,创建视图模型的对象并将属性值设置为

public ActionResult Edit(int id)
{
   var vm=new ItemViewModel { Id=id };
   var item = db.Items.FirstOrDefault(s=>s.Id==id);
   if(item!=null)
   {
     vm.Name = item.Name;
   }
   vm.Categories =db.Categories.Select(s=> new SelectListItem { Value=s.Id.ToString(),
                               Text=s.Name 
                            }).ToList();
   return View(vm);
}

您的视图将被强输入到您的视图模型

@model ItemViewModel
@using(Html.BeginForm())
{
  @Html.DropdDownListFor(s=>s.SelectedCategory,Model.Categories,"Select")
  @Html.HiddenFor(s=>s.Id)
  @Html.TextBoxFor(s=>s.Name)

  <input type="submit" />
}

在您的 HttpPost 操作中,从您的数据库中读取现有实体并更新您要更新的属性值。

[HttpPost]
public ActionResult Edit(ItemViewModel model)
{      
  if(ModelState.IsValid)
  {
     var item = d.Items.FirstOrDefault(s=>s.Id==model.Id);
     item.Name = model.Name;
     db.Entry(item).State = EntityState.Modified;
     db.SaveChanges();
     return RedirectToAction("Index");
  }
  model.Categories =db.Categories.Select(s=> 
          new SelectListItem { 
                               Value=s.Id.ToString(),
                               Text=s.Name }).ToList();
  return View(model);
}

确保在访问代码中的实体/对象之前添加足够的 NULL 检查。

于 2015-12-29T21:25:00.903 回答