Bind MVC DropDownlistFor () for Navigation Model Property

I am writing a simple learning application for my C # MVC class and our professor is using us in a terrible memory system using session and lists because he hasn't started teaching entity framework yet

the problem i'm running into is that when i try to bind the dropdown to my model it gives me an unexpected result.

im code used in view:

<div class="editor-label">
    @Html.LabelFor(model => model.Author)
</div>
<div class="editor-field">
    @Html.DropDownListFor(m => m.Author, new SelectList(new Lab2Repository().GetAuthors(), "Id", "Name"), "---- Select Category ----")
    @Html.ValidationMessageFor(m=>m.Author)
</div>
<div class="editor-label">
    @Html.LabelFor(m=>m.Category)
</div>
<div class="editor-field">
    @Html.DropDownListFor(m => m.Category, new SelectList(new Lab2Repository().GetCategories(), "Id", "Name"), "---- Select Category ----")
    @Html.ValidationMessageFor(m => m.Category)

</div>

      

and when i run this code it gives validation error no matter what is selected enter image description here

Repository code:

using System;
using System.Linq;
using System.Collections.Generic;
using Int422.Lab2.Data;
using System.Web;
using Int422.Lab2.Models;


public class Lab2Repository
{
    public Lab2Context Data { get; set; }
    public Lab2Repository()
    {
        Data = (Lab2Context)HttpContext.Current.Application["State"];
    }

    #region Retrieval

    public IEnumerable<Book> GetBooks()
    {
        return Data.Books;
    }
    public IEnumerable<Author> GetAuthors()
    {
        return Data.Authors.Select(obj => new Author(obj.Name) 
        { 
            Id = obj.Id, 
            Books = GetBooks().Where(b=>b.Author.Id == obj.Id).ToList() 
        });
    }

    public IEnumerable<Category> GetCategories()
    {
        return Data.Categories.Select(obj => new Category(obj.Name, obj.Description) 
        {  
            Id = obj.Id, 
            Books = GetBooks().Where(b=>b.Category.Id == obj.Id).ToList(),
        });


    } 
    #endregion
    #region Singles
    public Author GetAuthor(int id)
    {
        return GetAuthors().Where(obj => obj.Id == id).Single();
    }

    public Category GetCategory(int id)
    {
        return GetCategories().Where(obj => obj.Id == id).Single();
    }

    public Book GetBook(int id)
    {
        return Data.Books.Where(obj => obj.Id == id).Single();
    }
    #endregion
    #region Edit
    public void Edit(int id, Category rec)
    {
        if (id != rec.Id)
            throw new InvalidOperationException("Id Mismatch during edit process");

        int index = Data.Categories.IndexOf(Data.Categories.Single(p => p.Id == id));
        if (index == -1)
            throw new InvalidOperationException("Record not found no record to edit");
        Data.Categories[index] = rec;
        SaveChanges();

    }
    public void Edit(int id, Book rec)
    {
        if (id != rec.Id)
            throw new InvalidOperationException("Id Mismatch during edit process");

        int index = Data.Books.IndexOf(Data.Books.Single(p => p.Id == id));
        if (index == -1)
            throw new InvalidOperationException("Record not found no record to edit");
        Data.Books[index] = rec;
        SaveChanges();
    }


    public void Edit(int id, Author rec)
    {
        if (id != rec.Id)
            throw new InvalidOperationException("Id Mismatch during edit process");

        int index = Data.Authors.IndexOf(Data.Authors.Single(p => p.Id == id));
        if (index == -1)
            throw new InvalidOperationException(String.Format("Record id {0} not found", id));
        Data.Authors[index] = rec;
        SaveChanges();

    }
    #endregion
    #region Create
    //
    public int Create(Category m)
    {
        m.Id = Data.Categories.Max(o => o.Id) + 1;
        Data.Categories.Add(m);
        SaveChanges();
        return m.Id;

    }

    //adds new author to the collection returns the id 
    public int Create(Author m)
    {
        m.Id = Data.Authors.Max(o => o.Id) + 1;
        Data.Authors.Add(m);
        SaveChanges();
        return m.Id;
    }

    public int Create(Book m)
    {
        m.Id = Data.Authors.Max(o => o.Id) + 1;
        Data.Books.Add(m);
        SaveChanges();
        return m.Id;
    }
    #endregion
    #region Delete

    public void Delete(Author rec)
    {
        Data.Authors.Remove(Data.Authors.Single(o => o.Id == rec.Id));
        SaveChanges();
    }

    public void Delete(Category m)
    {
        Data.Categories.Remove(Data.Categories.Single(o => o.Id == m.Id));
        SaveChanges();
    }

    public void Delete(Book m)
    {
        Data.Books.Remove(Data.Books.Single(o => o.Id == m.Id));
        SaveChanges();
    }





    #endregion
    #region Session Persistance

    public void SaveChanges()
    {
        //save to session 
        HttpContext.Current.Application["State"] = Data;
        //refresh repo state from session 
        Data = (Lab2Context)HttpContext.Current.Application["State "];
    }

    #endregion




}

      

Models:

    public class Author
    {
        public Author(string name)
        {
            Name = name;
        }
        public Author()
        {
            Books = new List<Book>();
        }
        public int Id { get; set; }
        public string Name { get; set; }
        public virtual ICollection<Book> Books { get; set; }

    }

public class Category
    {

        public Category(string name, string desc)
        {
            Name = name;
            Description = desc;
            Books = new List<Book>();
        }
        public Category()
        {

        }
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public virtual ICollection<Book> Books  { get; set; }

    }

public class Book
    {
        public Book(string title, Author author, Category category, double retailPrice, double cost)
        {
            Title = title;
            Author = author;
            Category = category;
            RetailPrice = retailPrice;
            Cost = cost; 
        }
        public Book()
        {

        }

        public int Id { get; set; }
        public Category Category { get; set; }
        public Author Author { get; set; }
        public string Title { get; set; }
        public double RetailPrice { get; set; }
        public double Cost { get; set; }

    }

      

Controller:

public partial class BooksController : Controller
    {
        private Lab2Repository repo = new Lab2Repository();

        //
        // GET: /Books/

        public virtual ViewResult Index()
        {
            return View(repo.GetBooks());
        }

        //
        // GET: /Books/Details/5
        [GET("Books/{id:int}")]
        public virtual ActionResult Details(int id)
        {
            Book book = repo.GetBook(id);
            return View(book);
        }

        //
        // GET: /Books/Create

        public virtual ActionResult Create()
        {
            return View();
        } 

        //
        // POST: /Books/Create

        [HttpPost]
        public virtual ActionResult Create(Book book)
        {
            if (!ModelState.IsValid)
                return View(book);

            repo.Create(book);

            return RedirectToAction(MVC.Books.Index());

        }

        //
        // GET: /Books/Edit/5

        public virtual ActionResult Edit(int id)
        {
            Book book = repo.GetBook(id);
            return View(book);
        }

        //
        // POST: /Books/Edit/5

        [HttpPost]
        public virtual ActionResult Edit(int id, Book book)
        {
            if (!ModelState.IsValid)
                return View(book);

            repo.Edit(id, book);

            return RedirectToAction(MVC.Books.Details(id));
        }

        //
        // GET: /Books/Delete/5

        public virtual ActionResult Delete(int id)
        {
            Book book = repo.GetBook(id);
            return View(book);
        }

        //
        // POST: /Books/Delete/5

        [HttpPost, ActionName("Delete")]
        public virtual ActionResult DeleteConfirmed(int id)
        {
            Book book = repo.GetBook(id);
            repo.Delete(book);

            return RedirectToAction("Index");
        }


    }

      

Initializer:

public class Lab2StoreInitializer
{
public void Seed(Lab2Context c)
{

    //add categories 
    var cat_Programming = new Category("Programming", "Books about writing computer code and developing software") { Id = 1 };
    var cat_Politics = new Category("Politics", "books with politically charged subjects") { Id = 2 };
    var cat_NonFiction = new Category("Non-Fiction", "Books about real life events") { Id = 3 };


    c.Categories.Add(cat_Programming);
    c.Categories.Add(cat_Politics);
    c.Categories.Add(cat_NonFiction);


    //add authors 
    var noamChomsky = new Author("Noam Chomsky") { Id = 1};
    var howardZinn = new Author("Howard Zinn") { Id = 2 };
    var scottHanselman = new Author("Scott Hanselman") { Id = 3 };
    var philHaack = new Author("Phil Haack") { Id = 4 };
    var danielleSteele = new Author("Danielle Steele") { Id = 5 };
    var johnSkeet = new Author("John Skeet") { Id = 6 };
    var johnResig = new Author("John Resig") { Id = 7 };
    var scottKlein = new Author("Scott Klein") { Id = 8 };


    c.Authors.Add(noamChomsky);
    c.Authors.Add(howardZinn);
    c.Authors.Add(scottHanselman);
    c.Authors.Add(philHaack);
    c.Authors.Add(danielleSteele);
    c.Authors.Add(johnSkeet);
    c.Authors.Add(johnResig);
    c.Authors.Add(scottKlein);

    // add books 

    c.Books.Add(new Book("Manufacturing Consent", noamChomsky, cat_Politics, 16.57, 12.00) { Id = 1 });
    c.Books.Add(new Book("The Zinn Reader", howardZinn, cat_Politics, 35.75, 30.00) { Id = 2 });
    c.Books.Add(new Book("C# In Depth", johnSkeet, cat_Programming, 29.99, 25.00) { Id = 3 });
    c.Books.Add(new Book("Professional ASP.NET MVC 2", scottHanselman, cat_Programming, 34.99, 30.00) { Id = 4 });
    c.Books.Add(new Book("Professional MVC 4", philHaack, cat_Programming, 49.99, 45.00) { Id = 5 });
    c.Books.Add(new Book("His Bright Light: The Story of Nick Traina", danielleSteele, cat_NonFiction, 19.99, 14.00) { Id = 6 });
    c.Books.Add(new Book("Secrets of the JavaScript Ninja", johnResig, cat_Programming, 34.99, 29.99) { Id = 7 });
    c.Books.Add(new Book("Professional LINQ", scottKlein, cat_Programming, 39.99, 35.00) { Id = 8 });
    c.Books.Add(new Book("jQuery in Action", johnResig, cat_Programming, 49.99, 43.00) { Id = 9 });


    HttpContext.Current.Application["State"] = c;
    //base.Seed(c);
}
}

      

+3


source to share


2 answers


@Html.DropDownListFor(m => m.Author.Id, new SelectList(new Lab2Repository().GetAuthors(), "Id", "Name"), "---- Select Category ----")

      



+5


source


SelectList

uses a property Id

for Author

to identify it within Book

. However, your model Book

has the following meanings:

public Author Author { get; set; }

      

The default linker will not know how to link Id

to Author

. To fix this, you can declare it like this:

public int Author { get; set; }

      



Since Id

and Author

now have the same data type ( int

), it will work. The same goes for Category

:

public int Category { get; set; }

      

Your alternative is to write your own nexus and register it with MVC. Then you can force it to load the whole object Author

when only from the dropdown is passed int

. See this question for some suggestions with this: ASP.Net MVC Custom Model Binding Description

0


source







All Articles