我在我的 MVC 3 应用程序中遇到了同样的问题。我有一个创建新产品的 View ,并且可以将该产品分配给一个或多个类别。这是我的 EF Code First 模型类:
public class Product
{
public int ProductID { get; set; }
public string Name { get; set; }
public virtual ICollection<Category> Categories { get; set; }
}
public class Category
{
public int CategoryID { get; set; }
public string Name { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
因此,我为创建产品 View 创建了一个 View 模型,并包含了产品和类别列表:
public class ProductEditViewModel
{
public Product Product { get; set; }
public List<SelectListItem> CategorySelections { get; set; }
public ProductEditViewModel(Product product, List<Category> categories)
{
this.Product = product;
CategorySelections = categories.Select(c => new SelectListItem()
{
Text = c.Name,
Value = c.CategoryID.ToString(),
Selected = (product != null ? product.Categories.Contains(c) : false)
}).ToList();
}
}
因此,我呈现了一个 View ,其中包含名称输入和每个类别的复选框列表(名为“Product.Categories”)。当我的表单被回发时,我想保存产品及其相关类别(或者如果 ModelState 无效,则重新显示包含用户完整选择的类别的 View )。
[HttpPost]
public ActionResult Create(Product product)
{
if (ModelState.IsValid)
{
db.Products.Add(product);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(new ProductEditViewModel(product, db.Categories.ToList()));
}
当我这样做并选择一个或多个类别时,ModelState 无效并返回带有以下验证错误的编辑 View :
The value '25,2' is invalid. // 25 and 2 being the CategoryIDs
它不能将 25 和 2 绑定(bind)到实际的类别对象中,这对我来说很有意义,但是是否有使用自定义 ModelBinder 的标准方法允许我将 ID 转换为类别并将它们附加到上下文?
最佳答案
您可以尝试以下操作:在您的发布操作中绑定(bind)到您的 ViewModel 而不是 Product
:
[HttpPost]
public ActionResult Create(ProductEditViewModel viewModel)
{
if (ModelState.IsValid)
{
foreach (var value in viewModel.CategorySelections
.Where(c => c.Selected)
.Select(c => c.Value))
{
// Attach "stub" entity only with key to make EF aware that the
// category already exists in the DB to avoid creating a new category
var category = new Category { CategoryID = int.Parse(value) };
db.Categories.Attach(category);
viewModel.Product.Categories.Add(category);
}
db.Products.Add(viewModel.Product);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(new ProductEditViewModel(
viewModel.Product, db.Categories.ToList()));
}
我不确定这是否是“标准方式”。
编辑
当模型无效时 return
的情况在我上面的例子中不起作用,因为 viewModel.Product.Categories
集合是空的,所以你不会在 View ,而不是用户之前选择的项目。
我不知道您是如何将集合准确地绑定(bind)到 View (您的“复选框列表”?)但是当使用允许多项选择的 ListBox
时,似乎有一个解决方案这个答案的行:Challenges with selecting values in ListBoxFor .我刚刚在评论中问过 Darin,所选项目 ID 的列表是否也会在后期操作中绑定(bind)到 ViewModel,他证实了这一点。
关于entity-framework - 我如何 ModelBind 与 MVC 3 和 Entity Framework Code First 的多对多关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7259795/