ViewModel IEnum<>属性是否包含在局部视图中时返回null(不绑定)?

时间:2012-03-28 23:04:56

标签: asp.net-mvc asp.net-mvc-3 asp.net-mvc-4

我有一个ViewModel,它包含一个Product类型和一个IEnumerable<产品>类型。我有一个主视图,在页面顶部显示ViewModel.Product,但后来我有一个局部视图,呈现ViewModel.IEnumerable<产品>数据。在帖子上,第一级产品对象从ViweModel返回绑定,而ViewModel.IEnumerable<产品>回来了。

当然,如果我删除局部视图并移动IEnumerable<产品>查看主要查看内容回来绑定罚款。但是,我需要将这些Enumerable项放在局部视图中,因为我计划使用Ajax动态更新内容。

为什么IEnumerable<选取产品>在放置在局部视图中时,属性不会被绑定? THX!

型号:

public class Product
{
    public int ID { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

public class ProductIndexViewModel
{
    public Product NewProduct { get; set; }
    public List<Product> Products { get; set; }
}

public class BoringStoreContext
{
    public BoringStoreContext()
    {
        Products = new List<Product>();
        Products.Add(new Product() { ID = 1, Name = "Sure", Price = (decimal)(1.10) });
        Products.Add(new Product() { ID = 2, Name = "Sure2", Price = (decimal)(2.10) });
    }
    public List<Product> Products { get; set; }
}

查看:

主要index.cshtml:

@model ViewModelBinding.Models.ProductIndexViewModel

@using (@Html.BeginForm())
{
<div>
    @Html.LabelFor(model => model.NewProduct.Name)
    @Html.EditorFor(model => model.NewProduct.Name)
</div>
<div>
    @Html.LabelFor(model => model.NewProduct.Price)
    @Html.EditorFor(model => model.NewProduct.Price)
</div>

@Html.Partial("_Product", Model.Products)

<div>
    <input type="submit" value="Add Product" />
</div>
}

Parial View _Product.cshtml:

@model List<ViewModelBinding.Models.Product>

@for (int count = 0; count < Model.Count; count++)
{ 
    <div>
    @Html.LabelFor(model => model[count].ID)
    @Html.EditorFor(model => model[count].ID)
    </div>
    <div>
    @Html.LabelFor(model => model[count].Name)
    @Html.EditorFor(model => model[count].Name)
    </div>
    <div>
    @Html.LabelFor(model => model[count].Price)
    @Html.EditorFor(model => model[count].Price)
    </div>
}

控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        BoringStoreContext db = new BoringStoreContext();
        ProductIndexViewModel viewModel = new ProductIndexViewModel
        {
            NewProduct = new Product(),
            Products = db.Products
        };
        return View(viewModel);
    }

    [HttpPost]
    public ActionResult Index(ProductIndexViewModel viewModel)
    {
        // work with view model

        return View();
    }

}

1 个答案:

答案 0 :(得分:1)

使用@Html.Partial("_Product", Model.Products)时,输入字段的名称不正确。例如,而不是:

<input type="text" name="Products[0].ID" />

你得到:

<input type="text" name="[0].ID" />

只需查看生成的标记,您就会看到问题所在。这是因为当您使用Html.Partial时,不会保留导航上下文。输入字段名称不以集合的名称为前缀 - Products,因此模型绑定器无法正确绑定它。请查看following blog post以更好地了解预期的电线格式。

我建议您使用保留上下文的编辑器模板。所以而不是:

@Html.Partial("_Product", Model.Products)

使用:

@Html.EditorFor(x => x.Products)

现在将_Product.cshtml模板移至~/Views/Shared/EditorTemplates/Product.cshtml。此外,由于编辑器模板会自动识别Products属性为IEnumerable<T>,因此它将为此集合的每个项目呈现模板。因此,您的模板应该强烈键入单个产品,您可以摆脱循环:

@model Product
<div>
    @Html.LabelFor(model => model.ID)
    @Html.EditorFor(model => model.ID)
</div>
<div>
    @Html.LabelFor(model => model.Name)
    @Html.EditorFor(model => model.Name)
</div>
<div>
    @Html.LabelFor(model => model.Price)
    @Html.EditorFor(model => model.Price)
</div>

现在一切都按惯例运作,它将正确绑定。