1

I am following this Tutorial on ASP.NET MVC, specifically where it states that providing the String of "MovieType" to the Razor View as follows:@Html.DropDownList("MovieType") will provide the key to DropDownList to find a property in the ViewBag of type IEnumerable<SelectListItem>.

That works just fine.

However, I am unable to get the value that the User selects on my method with [HttpPost] attribute.

Here is my code and what I have tried thus far.

Controller

public class ProductController : Controller 
{
    private readonly ProductRepository repository = new ProductRepository();

    // Get: /Product/Create
    public ActionResult Create()
    {
        var categories = repository.FindAllCategories(false);
        var categorySelectListItems = from cat in categories
                                      select new SelectListItem()
                                          {
                                              Text = cat.CategoryName,
                                              Value = cat.Id.ToString()
                                          };
        ViewBag.ListItems = categorySelectListItems;
        return View();
    }

    [HttpPost]
    public ActionResult Create(Product product)
    {
        /** The following line is not getting back the selected Category ID **/
        var selectedCategoryId = ViewBag.ListItems;
        repository.SaveProduct(product);
        return RedirectToAction("Index");
    }
}

Razor cshtml View

@model Store.Models.Product

<h2>Create a new Product</h2>

@using (@Html.BeginForm())
{
    <p>Product Name:</p>
    @Html.TextBoxFor(m => m.ProductName)

    <p>Price</p>
    @Html.TextBoxFor(m => m.Price)

    <p>Quantity</p>
    @Html.TextBoxFor(m => m.Quantity)

    <p>Category</p>
    @Html.DropDownList("ListItems")
    <p><input type="submit" value="Create New Product"/></p>
}

I tried playing with the overloads for DropDownList, but I am not able to get the value back that the User is selecting.

If anyone sees what I am missing or has any ideas or suggestions, I would be very grateful. Thanks!

Update

Posting Product Model. Note, this was auto-generated by Entity Framework when I created the .edmx.

namespace Store.Models
{
    using System;
    using System.Collections.Generic;

    public partial class Product
    {
        public long Id { get; set; }
        public string ProductName { get; set; }
        public decimal Price { get; set; }
        public int Quantity { get; set; }
        public System.DateTime DateAdded { get; set; }
        public Nullable<long> CategoryId { get; set; }

        public virtual Category Category { get; set; }
    }
}
3
  • Does your Product object have a ListItems field? Commented Mar 29, 2013 at 19:21
  • @DaveA Nope. However, in my first Create() method, I put it into the ViewBag. I'm trying to figure out if there's a way I can separate the "getting" of the drop-down SelectListItem from the property that is sent back on the [HttpPost]. I really don't need the SelectListItems to come back when the User posts, only the ID of what they selected. Commented Mar 29, 2013 at 19:31
  • ListItems is the variable you bound to. you need ListItems param or object containing as param to action method Commented Mar 29, 2013 at 19:49

3 Answers 3

6

You are passing a model of type Store.Models.Product into your view. The other fields are binding to this model using a lambda expression, but @Html.DropDownList() does not bind to the model so when the model is returned in the HTTPPost the selection is not there.

You need to add your Category field to Store.Models.Product and then bind to that list using:

@Html.DropDownListFor(m => m.Category, ViewBag.ListItems)

Then MVC should properly bind your input control to the model.

As an example, this syntax does work:

int[] listItems = {1, 2, 3, 4};
SelectList selectList = new SelectList(listItems);
@Html.DropDownListFor(m => m.CategoryId, selectList);

Note that SelectList inherits from MultiSelectList which implements IEnumerable<SelectListItem>.

Sign up to request clarification or add additional context in comments.

3 Comments

This IS a better way. I wonder if it answers OP's question about specifically using the property-name-string approach and why it failed. (side point, you didn't cast the ViewBag")
+1 Thank you, you were correct in that I was not binding to the model, which led me in the right direction. However, I ended up not being able to use the lambda expression you provided, not sure why it didn't work. It did not like m=> m.Category (I also tried m=> m.CategoryId). I ended up with something with ugly syntax that functioned correctly but is not elegant, please see my answer.
This worked, I am now able to use the more elegant syntax that you provided. Answer accepted, thank you very much for your help!
2

Follow what Peter G. has mentioned in his answer, but just for informational purposes, you should also be able to change your Post controller to this:

[HttpPost]
public ActionResult Create(Product product, int ListItems)
{

}

As Peter has mentioned (once again, use his answer), the problem is that when your form posts, your DropDown list has a name of "ListItems" and there is nothing on your controller for it to bind to.

Comments

0

I ended up doing the following:

Controller

...
    [HttpPost]
    public ActionResult Create(Product product)
    {
        var categoryId = product.CategoryId;
        repository.SaveProduct(product);
        return RedirectToAction("Index");
    }
...

Razor cshtml View

...
<p>Category</p>
@Html.DropDownList("CategoryId", (IEnumerable<SelectListItem>) ViewData["ListItems"])
... 

It looks ugly and to be honest, I don't fully understand why I was not able to use a lambda expression like Peter suggested, @Html.DropDownListFor(m => m.CategoryId, ViewBag.ListItems).

To me, I've "got it to work", but want to understand why, and if there is a more elegant way I can do it.

When I typed in @Html.DropDownListFor(m => m.CategoryId, ViewBag.ListItems), IntelliSense would auto-fill m.CategoryId, but then would flag it in red, and I would get runtime error.

3 Comments

What does your Product model look like?
@PeterGluck I updated my original question to include it. It is generated by EF.
@Philip, see the example in my answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.