R – ASP.NET MVC Strongly Typed View for class that has a collection of objects

asp.net-mvcstrongly-typed-view

Consider this scenario:

class Book
{
    int id;
    List<Category> categories;
}

class Category
{
    int id;
    string name;
}

I have a strongly typed view for the class Book. When the librarian wants to edit the details of any Book, I want to display checkboxes with all possible categories. In case Book.categories contains a category, that check box will be checked.

The user can check and uncheck the boxes at will and then will click 'Submit'. I want that my controller function should be invoked with a parameter of type Book, with the new set of categories properly set.

How can this be done in ASP.NET MVC?

Best Answer

You might want to split this up into a couple of classes, one that is your book class, one for setting the view, and one for receiving the view's values. This may sound overdone but if nothing else it makes it so you aren't banging a square peg into a round hole. After all, if you just go with the Book class you have right now, you have to figure out how to make the view display everything you need (Say a bunch of check boxes for the categories... A list that your Book does not have completely) and then send it back to the controller still having to fit the same design as the Book class. To me that seems like in the long run a lot harder and maybe not possible without compromising the original book class design.

I would suggest something like this:

class ViewBookModel
{
  public ViewBookModel(Book book, IList<Categories> categoryList)
  {
    BookId = book.Id;
    BookName = book.BookName;
    CategoryList = categoryList;
  }

  public Int32 BookId { get; private set; }
  public String BookName { get; private set; }
  IList<Categories> CategoryList { get; set; }
}

And for posting back to the controller:

class ViewBookInModel
{
  public String BookId { get; set; }
  public String BookName { get; set }
  public Int32[] CategoryIds { get; set; }
}

And the markup would be something like:

<%
  foreach(var category in Model.CategoryList)
  {
%>
    <input type="checkbox" name="CategoryIds" value="<%= category.Id %>" />
<%
  }
%>

And the controller Method in:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UpdateBook(ViewBookInModel book)