1

I have created a sample MVC3 application for BookShop. I have a create action. In the create action users enter name of a book, author name and select a genre name. It is working without errors. But in the controller, I am not getting the selected genre name ( - the genre object comes as null). How do we correct it?

Note: When I write @Html.DropDownList("GenreId", String.Empty) the Model Binding capabilities built into ASP.NET MVC, will attempt to populate an object of that type using form inputs. E.g. it will try to set the book object’s GenreId value. But Book does not contain the property GenreId. However the dropdown can show the values by reading required values from ViewBag.

CODE

@model MyBookShopApp.Book

@{
ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm()) {

@Html.ValidationSummary(true)

<fieldset>

    <legend>BOOK</legend>


    <div >
        @Html.LabelFor(model => model.Title) :~: @Html.EditorFor(model => model.Title)
    </div>


    <div >
        @Html.LabelFor(model => model.Artist.Name )  :*: @Html.EditorFor(model => model.Artist.Name)
    </div>


    <div >
        @Html.LabelFor(model => model.GenreEntity.Name, "The Genre") ::   @Html.DropDownList("GenreId", String.Empty)
    </div>


    <p>
        <input type="submit" value="Create" />
    </p>

</fieldset>
}

<div>
 @Html.ActionLink("Back to List", "Index")
</div>

CONTROLLER

namespace MyBookShopApp.Controllers
{
public class StoreManagerController : Controller
{

    List<GenreEntity> listOfGenres = new List<GenreEntity>()
                                    {
                                       new GenreEntity { Name = "Fiction", GenreId = 1 },
                                       new GenreEntity { Name = "Science", GenreId = 2 },
                                       new GenreEntity { Name = "Religious", GenreId = 3 },
                                    };

    List<Book> bookList = new List<Book>()
                          {
                            new Book
                            {
                                BookId = 1,Title = "Book1",
                                GenreEntity = new GenreEntity { Name = "Fiction", GenreId = 1 },
                                Artist = new Artist { ArtistId = 1, Name = "Dinesh" }
                            },
                            new Book
                            {
                                BookId = 2,Title = "Book2",
                                GenreEntity = new GenreEntity { Name = "Science", GenreId = 2 },
                                Artist = new Artist { ArtistId = 1, Name = "Lijo" }
                            },
                            new Book
                            {
                                BookId = 3,Title = "Book3",
                                GenreEntity = new GenreEntity { Name = "Religious", GenreId = 3 },
                                Artist = new Artist { ArtistId = 1, Name = "Santhosh" }
                            }

                          };





    #region CREATE



    // GET: 
    public ActionResult Create()
    {
                    ViewBag.GenreId = new SelectList(listOfGenres, "GenreId", "Name");
        return View();
    }

    // POST:
    [HttpPost]
    public ActionResult Create(Book theBook)
    {
        if (ModelState.IsValid)
        {
            //Save the book in DB first and then redirectToAction.
            return RedirectToAction("Index");
        }

        return View(theBook);
    }

    #endregion


}
}

Book Class

public class Book
{
    public int BookId { get; set; } 
    public string Title { get; set; }
    public GenreEntity GenreEntity { get; set; }
    public Artist Artist { get; set; }

}

GenreEntity

  public class GenreEntity
{
    public string Name { get; set; }
    public int GenreId { get; set; }
}

Artist Class

 public class Artist
{
    public int ArtistId { get; set; }
    public string Name { get; set; }
}

REFERENCE:

  1. dropdown in mvc3 edit form

  2. How to use a Html.DropDownList in a strongly-typed view for a model containing a nullable enum property?

  3. MVC3 HTML helper doesn't update DropdownListFor on Submit the form

  4. on select change event - Html.DropDownListFor

  5. MVC3 @Html.DropDownListFor not populating selected item

Community
  • 1
  • 1
LCJ
  • 22,196
  • 67
  • 260
  • 418

2 Answers2

2

@Html.DropDownList("GenreId", String.Empty) creates a SELECT with the name GenreId. However MVC3 is expecting the name GenreEntity.Name to bind to Book.

The simple solution is to modify public ActionResult Create(Book theBook) to public ActionResult Create(Book theBook, string genreId) to receive the genreId that got posted back

Alternatively

@Html.LabelFor(model => model.GenreEntity.GenreId, "The Genre")
@Html.DropDownListFor(model => model.GenreEntity.GenreId, (SelectList)ViewBag.GenreId, String.Empty)

Remember to set your ViewBag inside the HttpPost Create method also.

Edit Corrected the property name from BookId to GenreId

Jeow Li Huan
  • 3,758
  • 1
  • 34
  • 52
  • I prefer to add the value to genreEntity of book object. How do we achieve that? Note: The "GenreId" is coming from ViewBag. – LCJ Feb 18 '12 at 10:03
  • Thanks. Your alternate suggestion works. But the GenreEntity object has only GenreId value. "Name" of the GenreEntity object is null. Any way to fill this value too? Are we using the proper approach/pattern to get the value? – LCJ Feb 18 '12 at 10:46
  • What I would do is to retrieve the value of Name etc on the server (e.g. through a DB query), using the GenreId. If you want to persist everything, you would end up with WebForms and the big ViewState that MVC3 is trying to avoid. – Jeow Li Huan Feb 18 '12 at 11:04
  • 1
    No. But you can always JSON encode everything (System.Web.Helpers.Json) and store it inside a hidden input field named ViewState. Please don't go there though... – Jeow Li Huan Feb 18 '12 at 11:11
  • 1
    For the benefit of others - the code I used is as follows: Genre :: @Html.DropDownListFor(model => model.GenreEntity.GenreId, (SelectList)ViewBag.GenreId, String.Empty) – LCJ Feb 18 '12 at 11:12
1

Your DropDown is trying to assign its value to a property called Book.GenreId. Your GenreEntity class has the GenreId property, not Book (based on the code you pasted above).

You can correct this by modifying the dropdown to this:

@Html.DropDownList("GenreEntity.GenreId", String.Empty)

This will tell MVC to assign the value of the drop down to Book.GenreEntity.GenreId.

Kyle Trauberman
  • 25,414
  • 13
  • 85
  • 121