Home > Software engineering >  InvalidOperationException: The model item passed into the ViewDataDictionary is of type Dbset[*] but
InvalidOperationException: The model item passed into the ViewDataDictionary is of type Dbset[*] but

Time:05-05

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 >
    <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.

CodePudding user response:

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);
}

CodePudding user response:

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.

  • Related