2012-03-28 4 views
11

Ho un modello di visualizzazione che contiene un tipo di classe Product e un tipo IEnumerable < Product>. Sul post l'oggetto prodotto di primo livello torna legato da viewmodel mentre l'enum del prodotto sta ritornando nullo.La proprietà View IEnumerable <> restituisce null (non vincolante) dal metodo post?

Perché la proprietà IEnumerable < Prouduct> non viene associata al mio modello di visualizzazione per post? Grazie!

Modelli:

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

Vista:

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

     } 
     } 

Controller:

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(); 
    } 
+0

Hai personalizzare l'EditorFor? – Shyju

+0

@Shyju: Salve, non ho supposto che se creo un editor per template per Product.cshtml potrei chiamare @ HTml.EditorFor (model => model.Products) e probabilmente funzionerà? – JaJ

+0

Sì, è possibile. Ho aggiunto una risposta con questo approccio. – Shyju

risposta

14

Non si sta utilizzando la vostra espressione lambda in modo corretto. È necessario accedere all'elenco dei prodotti tramite il modello. Prova a fare in questo modo:

@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++ 
    } 

Modifica

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) 
    { 
     // work with view model 

     return View(); 
    } 

Modello

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

Vista:

@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> 
} 
+1

Perché dovresti usare un ciclo foreach per simulare un ciclo regolare? E perché dovresti chiamare ripetutamente model.Products [count] quando hai già l'elemento nel ciclo foreach? – rossisdead

+0

@Xander - Grazie. Gli helper non rispondono molto bene all'utilizzo dell'espansione '.' quindi model.Products.item.ID' non funzionerà quindi l'indicizzazione. Ho dimenticato di rimuovere '.item' dalla soluzione e l'ho editato per riflettere la modifica che hai commentato nel tuo primo commento. –

+1

@rossisdead - Come commentato sopra, 'model.Products.item' non è valido qui bello come sarebbe da usare. Anche un 'for (int count = 0; count

7

Travis's answer risolverà il problema. Ecco un altro approccio utilizzando EditorTemplates

È possibile utilizzare un Editor template per visualizzare i prodotti e funzionerà correttamente.

1) Creare una cartella denominata "EditorTemplates" nella cartella di Vista/Casa

2) Aggiungere una vista chiamata "Products" all'interno di quella. Aggiungere questo codice a quella vista

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

e nella tua Vista principale, è possibile chiamare questo editor di modelli come questo

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

Sì, funziona anche così! ! – JaJ

Problemi correlati