entity-framework - 我如何 ModelBind 与 MVC 3 和 Entity Framework Code First 的多对多关系?

标签 entity-framework asp.net-mvc-3 viewmodel model-binding

我在我的 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/

相关文章:

android - Shared ViewModel 的 onCleared() 从未被调用

c# - 如何在 ASP.NET Identity 中编辑用户

asp.net-mvc-3 - ASP.NET MVC 3 RAZOR : How to use POST, 它给出错误 "Resource can not found"

database - MVC3 数据上下文最佳实践

asp.net - 在 web.config 中授权属性与授权节点

asp.net-mvc-3 - IEnumerable 的 mvc3 形式

android - 使用 ViewModel 和 ID 从 ROOM DB 访问数据

c# - Entity Framework 可以使用单个 SaveChanges() 添加许多相关实体吗?

.net - 当我从控制台运行 EF 代码迁移时 - 输入字符串格式不正确错误

entity-framework - 如何确定 EF 4.1 中具有引用属性的实体是否脏?