Posted ViewModel return null properties

I am having issues with a view model that constantly return null properties after a post. Below is my code (it could be a syntax issue or two calling a class or property the same name as i saw in other posts but i could not see any such issue in code):

VIEW MODEL:

public class ProductItem
    {
        public int ProductID { get; set; }
        public string Code { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public string LongDescription { get; set; }
        public int SupplierID { get; set; }
        public string Dimensions { get; set; }
        public double Price { get; set; }
        public bool On_Sale { get; set; }
        public double DiscountedPrice { get; set; }
        public string Thumbnail { get; set; }
        public string LargeImage { get; set; }
        public string LargeImage2 { get; set; }
        public string LargeImage3 { get; set; }
        public string CrossRef { get; set; }
        public byte Available { get; set; }
        public double Weight { get; set; }
        public byte Important { get; set; }
        public virtual ICollection<ProductCategory> ProductCategories { get; set; }

        // this is required on the page to allow products to be marked for deletion
        public bool IsForDelete { get; set; }
    }

    public class ProductListViewModel
    {
        public IEnumerable<ProductItem> ProductItems { get; set; }
        public IEnumerable<Category> CategoryItems { get; set; }
    }

CONTROLLER:

public ActionResult ProductList()
        {
            var productList = new ProductListViewModel();
            productList.ProductItems = productRepository.GetProductsWithDeleteOption().ToList();
            productList.CategoryItems = categoryRepository.GetCategories().ToList();
            return View(productList);
        }

        [HttpPost]
        public ActionResult ProductList(ProductListViewModel productViewModel, FormCollection formCollection, string submit)
        {            
            if (ModelState.IsValid)
            {
                // Check for submit action
                if (submit == "Change Sort")
                {
                    if (formCollection["Sortby"] == "ProductID")
                    {
                        OrderBy(productViewModel, formCollection, "m.ProductID");
                    }
                    else if (formCollection["Sortby"] == "Code")
                    {
                        OrderBy(productViewModel, formCollection, "m.Code");
                    }
                    else if (formCollection["Sortby"] == "Name")
                    {
                        OrderBy(productViewModel, formCollection, "m.Name");
                    }
                    else if (formCollection["Sortby"] == "Price")
                    {
                        OrderBy(productViewModel, formCollection, "m.Price");
                    }
                }
                else if (submit == "Delete all selected")
                {

                }
                else if (submit == "Update All")
                {

                }
                else if (submit == "Restrict Display")
                {

                }
            }
            return View(productViewModel);
        }

VIEW:

@model Admin.Models.ViewModels.ProductListViewModel

@{
    ViewBag.Title = "View Products";
}

@using (Html.BeginForm())
{
<h2>Product List as at @DateTime.Now.ToString("dd/MM/yyyy")</h2>
<table>
    <tr>
        <td>Sort by:</td>
        <td>
            <select name="Sortby">
                <option value="ProductID">ProductID</option>
                <option value="Code">Code</option>
                <option value="Name">Name</option>
                <option value="Price">Price</option>
            </select>
        </td>
        <td>
            <input type="radio" name="sortDirection" checked="checked" value="Asc" /> Ascending
            <input type="radio" name="sortDirection" value="Desc" /> Descending
        </td>
        <td>
            <input type="submit" name="submit" value="Change Sort" />
        </td>
    </tr>
    <tr>
        <td>Display only : (category)</td>
        <td>@Html.DropDownList("CategoryID", new SelectList(Model.CategoryItems, "CategoryID", "Name"), "All Categories")</td>
        <td colspan="2"><input type="submit" name="submit" value="Restrict Display" /></td>
    </tr>
    <tr>
        <td colspan="4"><br />Total Number of products: @Model.ProductItems.Count()</td>
    </tr>
</table>
<table>
    <tr>
        <th>
            Edit
        </th>
        <th>
            Code
        </th>
        <th>
            Name
        </th>
        <th>
            Price
        </th>
        <th>
            On_Sale
        </th>
        <th>
            DiscountedPrice
        </th>
        <th>
            Weight
        </th>
        <th>
            Delete
        </th>
        <th></th>
    </tr>

@for (var i = 0; i < Model.ProductItems.ToList().Count; i++)
{
    <tr>
        <td>
            @Html.HiddenFor(m => m.ProductItems.ToList()[i].ProductID)            
            @Html.ActionLink(Model.ProductItems.ToList()[i].ProductID.ToString(), "ProductEdit", new { id = Model.ProductItems.ToList()[i].ProductID })
        </td>
        <td>
            @Html.DisplayFor(m => m.ProductItems.ToList()[i].Code)
        </td>
        <td>
            @Html.DisplayFor(m => m.ProductItems.ToList()[i].Name)
        </td>
        <td>
            @Html.EditorFor(m => m.ProductItems.ToList()[i].Price)
        </td>
        <td>
            @Html.CheckBoxFor(m => m.ProductItems.ToList()[i].On_Sale, new { id = "On_Sale_" + Model.ProductItems.ToList()[i].ProductID })
        </td>
        <td>
            @Html.EditorFor(m => m.ProductItems.ToList()[i].DiscountedPrice)
        </td>
        <td>
            @Html.EditorFor(m => m.ProductItems.ToList()[i].Weight)
        </td>
        <td>
            @Html.CheckBoxFor(m => m.ProductItems.ToList()[i].IsForDelete, new { id = Model.ProductItems.ToList()[i].ProductID }) 
        </td>
        <td>
            @Html.ActionLink("Edit", "ProductEdit", new { id = Model.ProductItems.ToList()[i].ProductID }) |
            @Html.ActionLink("Details", "Details", new { id = Model.ProductItems.ToList()[i].ProductID }) |
            @Html.ActionLink("Delete", "Delete", new { id = Model.ProductItems.ToList()[i].ProductID })
        </td>
    </tr>
}

</table>
<p>
    <input name="submit" type="submit" value="Delete all selected" />
</p>
<p>
    <input name="submit" type="submit" value="Update All" />
</p>

<p>
    @Html.ActionLink("Add a new product", "ProductAdd")
</p>

}

In the post action, the productViewModel argument has the ProductItems and CategoryItems properties as null.


Yes it will be null on post back. I have a similar table in one of my projects and this is what I would have done given my situation.

You could change your view model to look like this then you don't have to do so many converting to lists in your view:

public class ProductListViewModel
{
     public List<ProductItem> ProductItems { get; set; }

     public List<Category> CategoryItems { get; set; }
}

Now in you view it could look something like this (this is just part of it, then rest you can just go and add):

@for (int i = 0; i < Model.ProductItems.Count(); i++)
{
     <tr>
          <td>
               @Html.DisplayFor(m => m.ProductItems[i].Name)
               @Html.HiddenFor(m => m.ProductItems[i].Name)
          </td>
     </tr>
     <tr>
          <td>
               @Html.CheckBoxFor(m => m.ProductItems[i].IsForDelete)
          </td>
     </tr>
}

Add the code and do some debugging to see how the values are returned on submit

I hope this helps.


Ok, so there are two problems.

  • I don't understand why you want to post list of the CategoryItems You should only expect the selected category and not the list

  • The problem with ProductItems is the name generated for <input> tags. Currently, the name being generated is name="[0].Price" whereas it should have been name="ProductItems[0].Price"

  • I changed the following code

    @Html.EditorFor(m => m.ProductItems.ToList()[i].Price)
    

    to

    @Html.EditorFor(m => m.ProductItems[i].Price)
    

    and it worked.

    Note: I changed IEnumerable<ProductItem> ProductItems to List<ProductItem> ProductItems in ProductListViewModel

    链接地址: http://www.djcxy.com/p/53966.html

    上一篇: 为什么空模型返回post方法?

    下一篇: 发布ViewModel返回null属性