[SOLVED] InvalidOperationException: There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key 'GenreId'

Issue

I have this code. I’ve watched on other stack overflow posts, but nothing works for me. Do I miss something? I need to make some dropdowns for genre, publisher and author and I couldn’t find anything which could help me. I tried viewbag because I found it in many places, but it’s not working for me. I don’t know if viewbag is for .net mvc core 3.1

Book Model

 public class Book
{
    public int BookId { get; set; }

    public string Title { get; set; }

    public int AvailableCopies { get; set; }

    public int TotalCopies { get; set; }

    public string GenreId { get; set; }

    public int PublisherId { get; set; }

    public Genre Genre { get; set; }

    public Publisher Publisher { get; set; }

    public ICollection<BookAuthor> BookAuthors { get; set; }

    public ICollection<BorrowProcess> BorrowProcesses { get; set; }
}

Books Controller:

 //POST: Books/Create
    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult Create([Bind("BookId,Title,TotalCopies,AvailableCopies")] Book book)
    {

        if (ModelState.IsValid)
        {

            ViewBag.GenreId = new SelectList(_genres, "GenreId", "Name");
            _bookService.AddBook(book);
            _bookService.Save();
            return RedirectToAction(nameof(Index));
        }
        return View(book);

    }

Create View:

@model LibraryApplication.Models.Book

@{
    ViewData["Title"] = "Create";
}

<h1>Create</h1>

<h4>Book</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Title"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="AvailableCopies"></label>
                <input asp-for="AvailableCopies" class="form-control" />
                <span asp-validation-for="AvailableCopies" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="TotalCopies"></label>
                <input asp-for="TotalCopies" class="form-control" />
                <span asp-validation-for="TotalCopies" class="text-danger"></span>
            </div>
            @*<div class="form-group">
                <label asp-for="GenreId"></label>
                <select asp-for="GenreId" class="form-control" asp-items="ViewBag.GenreId"></select>
            </div>*@
        <div class="form-group">
            @Html.DropDownList("GenreId", null, new { @class = "form-control" })
            @Html.ValidationMessageFor(model => model.GenreId)
        </div>
            <div class="form-group">
                <label asp-for="PublisherId"></label>
                <select asp-for="PublisherId" class="form-control" asp-items="ViewBag.PublisherId"></select>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

I’m using MVC Core 3.1. What could be the problem?

Update:

public BooksController(BookService bookService, AuthorService authorService, GenreService genreService, PublisherService publisherService)
 {
 _bookService = bookService;
 _authorService = authorService; 
_genreService = genreService;
 _publisherService = publisherService;
 _genres = _genreService.GetGenres(); } 
// GET: Books 
public IActionResult Index(string SearchString) 
{ 
var books = _bookService.GetBooks();
 return View(books); 
} 
.....

Solution

Fix DropDownList. Try this

 @Html.DropDownListFor(model => model.GenreId, @ViewBag.GenreId, "Choose an option", new { @class = "form-control" })

and you need one more action

     [HttpGet]
     public IActionResult   Create()
    {

            ViewBag.GenreId = new SelectList(_genres, "GenreId", "Name");
            
           var model = new Book();
        return View(model);

    }

Answered By – Serge

Answer Checked By – Terry (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *