Свойство View Model IEnumerable <> возвращает значение null (не обязательное) из метода post?

У меня есть модель представления, которая содержит тип класса Product и IEnumerable < Продукт > тип. На почте объект продукта первого уровня возвращается с привязкой к viewmodel, тогда как перечисление продукта возвращается null.

Почему IEnumerable < Свойство Prouduct > не привязано к моей модели представления за сообщение? спасибо!

Модели:

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 IEnumerable<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;}
}

Вид:

@model 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>
    <div>
        <input type="submit" value="Add Product" />
    </div>

        foreach (var item in Model.Products)
        { 
         <div>
        @Html.LabelFor(model => item.ID)
        @Html.EditorFor(model => item.ID)
    </div>
    <div>
        @Html.LabelFor(model => item.Name)
        @Html.EditorFor(model => item.Name)
    </div>
    <div>
        @Html.LabelFor(model => item.Price)
        @Html.EditorFor(model => item.Price)
    </div>

        }
       }

Контроллер:

public class HomeController : Controller
{
    BoringStoreContext db = new BoringStoreContext();

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

    [HttpPost]
    public ActionResult Index(ProductIndexViewModel viewModel)
    {
        // ???? viewModel.Products is NULL here
        // ???? viewModel.NewProduct comes back fine

        return View();
    }

Ответ 1

Вы не используете свое лямбда-выражение правильно. Вы должны получить доступ к списку продуктов через модель. Попробуйте сделать это следующим образом:

@count = 0
foreach (var item in Model.Products)
    { 
     <div>
    @Html.LabelFor(model => model.Products[count].ID)
    @Html.EditorFor(model => model.Products[count].ID)
</div>
<div>
    @Html.LabelFor(model => model.Products[count].Name)
    @Html.EditorFor(model => model.Products[count].Name)
</div>
<div>
    @Html.LabelFor(model => model.Products[count].Price)
    @Html.EditorFor(model => model.Products[count].Price)
</div>
@count++
    }

Edit

Контроллер:

BoringStoreContext db = new BoringStoreContext();

    public ActionResult Index()
    {
        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();
    }

Model

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; }
}

Вид:

@model 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>


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

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

Ответ 2

Тревис ответ рассмотрит проблему. Вот еще один подход, использующий EditorTemplates

Вы можете использовать Editor template для отображения Продуктов, и он будет работать нормально.

1) Создайте папку под названием "EditorTemplates" в папке Views/Home

2) Добавьте внутри него представление под названием "Products". Добавьте этот код в это представление

@model SO_MVC.Models.Product
@{
   Layout = null;
}
<p>
  @Html.LabelFor(x=>x.ID)
  @Html.EditorFor(x=>x.ID) 
</p>
<p>
  @Html.LabelFor(x=>x.Name)
  @Html.EditorFor(x=>x.Name)
</p>
<p>
  @Html.LabelFor(x=>x.Price)
  @Html.EditorFor(x=>x.Price)
</p> 
@Html.HiddenFor(x=>x.Id)

и в вашем основном представлении вы можете вызвать этот шаблон редактора, как этот

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