ViewModel ICollection v IEnumerable

Dean Everhart 1,541 Reputation points
2023-05-02T15:58:35.3866667+00:00

Models: Item and Reference (Note.Models...)

ViewModel: ItemReference (Note.Models.View.ItemReference)

View: ItemReference (Note.Views.ItemReference)

Controller: Item, ItemReference Action Method (Controllers.ItemController...)

Environment: Net Core 6 MVC, Visual Studio Community 2022 (64 bit), WIndows 11

Error:

InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'System.Collections.Generic.List1[Note.Models.Item]', but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.IEnumerable1[Note.Models.View.ItemReference]'.

Change Made:

Set Models Navigation Properties and View to IEnumerable (pictured below)

**
Models** Navigation Properties set to IEnumerable

        public IEnumerable<Attribution>? Attribution { get; set; }

        /*public ICollection<Attribution>? Attribution { get; set; }*/      // original

ViewModel

using System.Net;

namespace Note.Models.View
{
    public class ItemReference
    {
        public Item Item { get; set; }      

        public Reference Reference { get; set; }      

Context

using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Note.Models;

namespace Note.Data
{
    public class ApplicationDbContext : IdentityDbContext
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }
        public DbSet<Note.Models.Item>? Item { get; set; }
        public DbSet<Note.Models.Reference>? Reference { get; set; }
        public DbSet<Note.Models.Attribution>? Attribution { get; set; }
        public DbSet<Note.Models.Forum>? Forum { get; set; }
    }
}

View (no errors displayed)
User's image

Controller: ItemReference Action Method

       // GET: Item
        public async Task<IActionResult> ItemReference()
        {
            return _context.Item != null ?
                        View(await _context.Item.ToListAsync()) :
                        Problem("Entity set 'ApplicationDbContext.Item'  is null.");
        }

Result When Run:

Error: (Same as above)

InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'System.Collections.Generic.List1[Note.Models.Item]', but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.IEnumerable1[Note.Models.View.ItemReference]'.


If I set Model navigation properties and View all to ICollection

Model Navigation Properties

        public ICollection<Attribution>? Attribution { get; set; }     // original

View

@model ICollection<Note.Models.View.ItemReference>

Errors (red underline)
User's image

Severity Code Description Project File Line Suppression State

Error (active) CS1061 'ICollection<ItemReference>' does not contain a definition for 'Item' and no accessible extension method 'Item' accepting a first argument of type 'ICollection<ItemReference>' could be found (are you missing a using directive or an assembly reference?) C:\Users\User1\Desktop_Tech_Notes_Tech\Tech\Note\Views\Item\ItemReference.cshtml 18

Developer technologies | ASP.NET | ASP.NET Core
Developer technologies | ASP.NET | Other
{count} votes

Accepted answer
  1. Bruce (SqlWork.com) 78,086 Reputation points Volunteer Moderator
    2023-05-02T16:44:36.9866667+00:00

    you controller code:

    View(await _context.Item.ToListAsync()) 
    
    

    is sending List<Note.Models.Item> object to the view. its can downcast to:

    @model IEnumerable<Note.Models.Item> 
    @model ICollection<Note.Models.Item> 
    
    

    but a Note.Models.Item can not be cast to a Note.Models.View.ItemReference as they are different types

    0 comments No comments

3 additional answers

Sort by: Most helpful
  1. Xinran Shen - MSFT 2,091 Reputation points
    2023-05-03T01:51:39.3333333+00:00

    Hi @Dean Everhart,

    Let's check the error message:

    System.Collections.Generic.List[Note.Models.Item], but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.IEnumerable[Note.Models.View.ItemReference]

    The view requires a IEnumerable<ItemReference> model, But in the backend you pass a List<Item> model, ItemReference and Item are two different models, they can't match. Then you get this error message in your project. So you need to return List<ItemReference> in controller to make the model consistent on the front and back ends.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,

    Xinran Shen

    0 comments No comments

  2. Dean Everhart 1,541 Reputation points
    2023-05-03T15:02:26.8366667+00:00

    **Follow-Up Questions
    **
    Tried two different changes. I think attempt B (below) is closer to what I'm suppose to be doing.

    A.

    Re:
    "So you need to return List<ItemReference> in controller"

    If I change the ItemReference Action Method in the Index Controller to...
    return List (ItemReference);

            // GET: Item
            public async Task<IActionResult> ItemReference()
            {
                return List(ItemReference);
            }
    

    Error:
    CS1963 An expression tree may not contain a dynamic operation C:\Users\User1\Desktop_Tech_Notes_Tech\Tech\Note\Views\Item\ItemReference.cshtml 20

    View

    User's image


    B.
    If I change the references to "Item" in the Action Method to "ItemReference"

            // GET: Item
            public async Task<IActionResult> ItemReference()
            {
                return _context.ItemReference != null ?
                            View(await _context.ItemReference.ToListAsync()) :
                            Problem("Entity set 'ApplicationDbContext.Item'  is null.");
            }
    

    Error:
    CS1061 'ApplicationDbContext' does not contain a definition for 'ItemReference' and no accessible extension method 'ItemReference' accepting a first argument of type 'ApplicationDbContext' could be found (are you missing a using directive or an assembly reference?) Note C:\Users\User1\Desktop_Tech_Notes_Tech\Tech\Note\Controllers\ItemController.cs 41 Active

    I do not have viewModel listed in context. Do the viewmodels get listed in the context alongside the models?

    Context:

    using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
    using Microsoft.EntityFrameworkCore;
    using Note.Models;
    
    namespace Note.Data
    {
        public class ApplicationDbContext : IdentityDbContext
        {
            public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
                : base(options)
            {
            }
            public DbSet<Note.Models.Item>? Item { get; set; }
            public DbSet<Note.Models.Reference>? Reference { get; set; }
            public DbSet<Note.Models.Attribution>? Attribution { get; set; }
            public DbSet<Note.Models.Forum>? Forum { get; set; }
        }
    }
    

  3. Bruce (SqlWork.com) 78,086 Reputation points Volunteer Moderator
    2023-05-03T15:19:53.63+00:00

    You seem to lack basic understanding of types and classes. You should do some c# tutorials to learn about classes and types. You will also need to understand interfaces.

    the view model is the object instance passed to the view. If you want to pass entity properties you need to add them to the view model and set their values.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.