0

重要提示:我已编辑问题以反映 Jannagy02 的答案,从而消除了 Dropdownlist 问题

我有一个关于 ASP.NET MVC 4 和实体框架的概念性问题。

首先,让我们看看我的模型:电火花加工

这所有广告都在一台设备上。一个设备有一个类别、一个制造商、一个状态和 0..n 条评论。这是被剥离的。在学习 MVC 时,我不想过于复杂。因此,让我们只关注DeviceCategory忽略诸如存储库和工作单元模式之类的东西。

在我设置好之后,脚手架发挥了作用,生成的视图只显示了Name设备的属性。

我的计划是,在创建或更新设备时,用户(不是管理员)只能从已经存在的类别中进行选择。因此是一个下拉列表。

为此,我创建了一个 ViewModel:

public class DeviceEditViewModel
{
    public Device dev { get; set; }

    public int? SelectedManufactor { set; get; }
    public IEnumerable<SelectListItem> Manufactors { get; set; }

    public int? SelectedCategory { set; get; }
    public IEnumerable<SelectListItem> CategoriesListItems { get; set; }
}

GET 编辑方法如下所示:

public ActionResult Edit(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    var device = db.Devices.Find(id);
    var vm = new DeviceEditViewModel
                 {
                      dev = device,
                      Categories = db.Categories.ToList().Select(x => new SelectListItem 
                      {
                          Value = x.ID.ToString(), 
                          Text = x.Name, 
                          Selected = x == device.Category
                      })
                  };
    return View(vm);
}

这是我的第一个问题:生成的下拉列表没有获取设备的实际类别。那么我该如何选择实际类别作为选定值呢?

其次,当我点击保存按钮时,如何将这个选定的 ListItem 作为设备模型的类别注入,这如何反映在 post 方法中,如下所示:

//Edited to reflect answer
public ActionResult Edit(DeviceEditViewModel editViewModel)
{
    if (ModelState.IsValid)
    {
        Device device = editViewModel.dev;
        if (editViewModel.SelectedCategory != null)
        {
            Category selectedCat = db.Categories.Single(x => x.ID == editViewModel.SelectedCategory.Value);
            device.Category = selectedCat;
        }

        db.Entry(device).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(editViewModel);
}

这是我的观点的 DropDownList 部分:

<div class="control-group">
    @Html.LabelFor(model => model.dev.Category, new { @class = "control-label" })

    <div class="controls">
        @Html.DropDownListFor(x => x.CategoriesListItems, Model.CategoriesListItems)
        @Html.ValidationMessageFor(model => model.dev.Category, null, new { @class = "help-inline" })
    </div>
</div>

剩下的问题在于 POST 方法。我已经写了更长的时间以便能够更好地调试它。实际问题是:

设备使用类别更新,但在db.SaveChanges()调用之后它不会被写入数据库。

4

2 回答 2

1

首先修改您的 ViewModel 以便它可以包含选定的值:

public class DeviceEditViewModel
{
    public Device dev { get; set; }
    public IEnumerable<SelectListItem> Manufactors { get; set; }

    public int? SelectedCategory { set; get; }
    public IEnumerable<SelectListItem> Categories { get; set; }
    public IEnumerable<SelectListItem> Status { get; set; }
}

第二:

在视图中绑定 SelectedCategory 以便它可以发布:

@Html.DropDownListFor(m => m.SelectedCategory, m.Categories)

或使用这个

@Html.DropDownListFor(m => m.SelectedCategory, new SelectList(m.Categories, "ValuePropertyName", "TextPropertyName"))

并将 ViewModel 发布到编辑而不是设备:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(DeviceEditViewModel devm)
{
    if (ModelState.IsValid)
    {
        devm.device.CategoryId = devm.SelectedCategory; // <- Main thing to do
        db.Entry(devm.device).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(devm);
}
于 2013-10-20T08:25:01.630 回答
0

在我让这个问题休息几天后,我找到了一个可行的解决方案。实际编辑项目及其属性并将其保存到数据库的最后一个问题是,一旦我设法缩小可能发生错误的位置,这非常简单。

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(DeviceEditViewModel editViewModel)
{
    if (ModelState.IsValid)
    {
        //non-working: Device device = editViewmodel.env;
        Device device = db.Devices.Single(x => x.Id == editViewModel.dev.Id); /*working*/
        if (editViewModel.SelectedCategory != null)
        {
           device.Category = db.Categories.Where(x => x.ID == editViewModel.SelectedCategory).Select(x => x).Single();
        }
        db.Entry(device).State = EntityState.Modified;
        db.Devices.AddOrUpdate(device);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
        return View(editViewModel);
}

我没有使用使用的 Viewmodel,而是通过比较 ID 从数据库中获取要编辑的设备,并在该实体上调用 AddOrUpdate()。

现在就像一个魅力。但是,我会将解决方案单击到我的下拉列表助手答案。否则就不公平。

于 2013-10-22T07:45:48.750 回答