我有两个自动生成的数据库模型(Product和ProductDetails),它们已合并到ViewModel中,因此可以一次编辑所有数据.
令我感到困惑的是我应该在视图内迭代Product_ProductCategoryAttributes(在ProductDetail模型内)的ICollection以便允许.NET自动将属性绑定到ViewModel的部分.我尝试过使用for和foreach循环,但都没有成功,因为控件使用错误的名称(需要自动绑定)创建.
产品型号
public partial class Product
{
public Product()
{
this.ProductDetail = new HashSet<ProductDetail>();
}
public int idProduct { get; set; }
public int idProductCategory { get; set; }
public string EAN { get; set; }
public string UID { get; set; }
public bool Active { get; set; }
public virtual ProductCategory ProductCategory { get; set; }
public virtual ICollection<ProductDetail> ProductDetail { get; set; }
}
产品详细信息模型
public partial class ProductDetail
{
public ProductDetail()
{
this.Product_ProductCategoryAttribute = new HashSet<Product_ProductCategoryAttribute>();
}
public int idProductDetail { get; set; }
public int idProductCategory { get; set; }
public int idMeta { get; set; }
public int idProduct { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual Meta Meta { get; set; }
public virtual Product Product { get; set; }
public virtual ICollection<Product_ProductCategoryAttribute> Product_ProductCategoryAttribute { get; set; }
public virtual ProductCategory ProductCategory { get; set; }
}
ProductViewModel-一个产品可以有多个ProductDetails
public class ProductViewModel
{
public Product Product { get; set; }
public List<ProductDetail> ProductDetails { get; set; }
}
视图(有意省略一些代码)
@for (int i = 0; i < Model.ProductDetails.Count(); i++)
{
@Html.TextAreaFor(model => model.ProductDetails[i].Description, new { @class = "form-control", @rows = "3" })
@for (int j = 0; j < Model.ProductDetails[i].Product_ProductCategoryAttribute.Count(); j++)
{
@Html.HiddenFor(model => model.ProductDetails[i].Product_ProductCategoryAttribute.ElementAt(j).idProductCategoryAttribute)
@Html.TextBoxFor(model => model.ProductDetails[i].Product_ProductCategoryAttribute.ElementAt(j).Value, new { @class = "form-control" })
}
}
第二个for循环之外的所有控件均已正确命名,例如. ProductDetails [0] .Description,但是在第二个for循环中生成的控件通过属性值(在这种情况下为Value和idProductCategoryAttribute)获得名称.如果我没有记错的话,一种解决方案是将ICollection转换为IList,但是自动生成模型不会是最好的选择.
解决方法:
您不能在HTML帮助器的lambda中使用ElementAt().将生成的名称将只是不带索引的字段的名称,这将允许填充发布的值.
您应该使用索引来遍历整个视图模型,以便实际生成的名称匹配.
所以这:
@Html.HiddenFor(model => model.ProductDetails[i].Product_ProductCategoryAttribute.ElementAt(j).idProductCategoryAttribute)
应该是这样,或类似的:
@Html.HiddenFor(model => model.ProductDetails[i].Product_ProductCategoryAttribute[j].idProductCategoryAttribute)
至于将模型从ICollection更改为IList,这是很好的,因为IList继承自ICollection.但是正如您所说的那样,它是自动生成的,如果您使用的是代码优先实体框架或类似的框架,那可能没问题.
真正的解决方案是将您的传入模型(视图模型)映射到自动生成的ICollection <列出并再次返回,具体取决于您要发布还是获取. 在下面的示例中,我们将获取发布的值,并将其映射到自动生成的Product对象并对其进行操作.
///
/// ProductViewModel incoming model contains IList<> fields, and could be used as the view model for your page
///
[HttpPost]
public ActionResult Index(ProductViewModel requestModel)
{
// Create instance of the auto generated model (with ICollections)
var product = new Product();
// Map your incoming model to your auto generated model
foreach (var productDetailViewModel in requestModel)
{
product.ProductDetail.Add(new ProductDetail()
{
Product_ProductCategoryAttribute = productDetailViewModel.Product_ProductCategoryAttribute;
// Map other fields here
}
}
// Do something with your product
this.MyService.SaveProducts(product);
// Posted values will be retained and passed to view
// Or map the values back to your valid view model with `List<>` fields
// Or pass back the requestModel back to the view
return View();
}
ProductViewModel.cs
public class ProductViewModel
{
// This shouldn't be here, only fields that you need from Product should be here and mapped within your controller action
//public Product Product { get; set; }
// This should be a view model, used for the view only and not used as a database model too!
public List<ProductDetailViewModel> ProductDetails { get; set; }
}