InvalidOperationException: The model item passed into the ViewDataDictionary is of type Dbset[*] but this ViewDataDictionary of type [*]

I just can't understand I tried everything I could so I hope you guys can help me. Error message :

InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1[BookStore1.Models.Book]', but this ViewDataDictionary instance requires a model item of type 'BookStore1.Models.Account'.

That's like an online book-store and I was trying to make an action with which you can display all books in the database and edit them as an admin. That's my book model:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace BookStore1.Models
{
    public class Book
    {
        [Key]
        public int Id { get; set; }
        [Required]
        public string? Name { get; set; }
        [Required]
        public string? Author { get; set; } = "Unknown";
        [Required]
        public int Price { get; set; }
        [NotMapped]
        public IFormFile? Image { set; get; }
    }
}

that's my admin controller:

using BookStore1.Data;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using BookStore1.Models;

namespace BookStore1.Controllers
{
    [Authorize(Policy = "HasToBeAdmin")]
    public class AdminController : Controller
    {
        private readonly AppDataContext _database;
        private readonly IWebHostEnvironment _webHostEnvironment;
        public AdminController(AppDataContext database, IWebHostEnvironment webHostEnvironment)
        {
            _database = database;
            _webHostEnvironment = webHostEnvironment;
        }
        public IActionResult ShowBooks()
        {
            var books = _database.Books;
            return View(books);
        }
        [HttpGet]
        public IActionResult AddBook()
        {
            return View();
        }
        public async Task<IActionResult> AddBook(Book book)
        {
            if (ModelState.IsValid)
            {
                string wwwRootPath = _webHostEnvironment.WebRootPath;
                string fileName = Path.GetFileNameWithoutExtension(book.Image.FileName);
                string extention = Path.GetExtension(book.Image.FileName);
                string path = Path.Combine(wwwRootPath + "/booksImages", fileName);
                using (var fileStream = new FileStream(path, FileMode.Create))
                {
                    await book.Image.CopyToAsync(fileStream);
                }
                _database.Books.Add(book);
                _database.SaveChanges();
                return RedirectToAction("ShowBooks", "Admin");

            }
            return View(book);
        }
    }
}

The view that won't view:

@model IEnumerable<BookStore1.Models.Book>

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

<h1>ShowBooks</h1>

<p>
    <a asp-action="Create">Create New</a>
</p>
<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Name)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Author)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Price)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Name)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Author)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Price)
            </td>
            <td>
                <a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
                <a asp-action="Details" asp-route-id="@item.Id">Details</a> |
                <a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
            </td>
        </tr>
}
    </tbody>
</table>

database context:

using Microsoft.EntityFrameworkCore;
using BookStore1.Models;

namespace BookStore1.Data
{
    public class AppDataContext: DbContext
    {
        public AppDataContext(DbContextOptions<AppDataContext> options): base(options)
        {
        }
        public DbSet<Account> Accounts { get; set; }
        public DbSet<Book> Books { get; set; }
    }
}

Thank for your time and help.

2 answers

  • answered 2022-05-04 16:12 Serge

    you have to fix the action, to convert a dbset to a list and add name of the view to the action if name is not "ShowBooks.cshtml"

    public IActionResult ShowBooks()
    {
         var books = _database.Books.ToList();
         return View("viewName", books);
    }
    

  • answered 2022-05-05 03:18 Yiyi You

    If the view you shown above is ShowBooks.You only need to use _database.Books.ToList() as Serge said. You use @model IEnumerable<BookStore1.Models.Book> in the view,and you pass System.Collections.Generic.List1[BookStore1.Models.Book]` to the view,it's correct.

    InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'System.Collections.Generic.List`1[BookStore1.Models.Book]', but this ViewDataDictionary instance requires a model item of type 'BookStore1.Models.Account'.

    For the error,the view will contains @model BookStore1.Models.Account.You need to find the view which contains it,and check the data passed from action.

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum