Model Derived from Identity Error

kobosh 176 Reputation points
2021-11-09T18:53:23.21+00:00

I created .net core (5) app with authentication. Now I wanted to manage created database. I added model derived from Identity.IdentityUser to use it in scaffolding view. I added migration and updated database. When I run app I get:

InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'System.Collections.Generic.List1[Microsoft.AspNetCore.Identity.IdentityUser]', but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.List1[ContactManager.Models.UserModel]'.

Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary.EnsureCompatible(object value)
My controller:

 public class UsersController : Controller
    {
        private ApplicationDbContext db;
        public UsersController(ApplicationDbContext _db)
        {
            db = _db;
        }
        // GET: UsersController
        public async Task< ActionResult> Index()
        {
            var result = await db.Users.ToListAsync();
            return View(result );
        }
.................
................
}

My Model:

public   class UserModel:Microsoft.AspNetCore.Identity.IdentityUser
    {       

    }

My view

@model List<ContactManager.Models.UserModel>

@{
    ViewData["Title"] = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h1>Index</h1>

<p>
    <a asp-action="Create">Create New</a>
</p>
<table class="table">
    <thead>
        <tr>
            <th>
                User Name
            </th>
            <th>
                Email
            </th>

            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.UserName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Email)
            </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>
Entity Framework Core
Entity Framework Core
A lightweight, extensible, open-source, and cross-platform version of the Entity Framework data access technology.
737 questions
0 comments No comments
{count} votes

Accepted answer
  1. Michael Taylor 54,051 Reputation points
    2021-11-09T19:06:00.547+00:00

    The issue is a type mismatch between what your controller action is passing to the view and what the view is expecting.

    var result = await db.Users.ToListAsync();
    return View(result );
    

    result is of type List<IdentityUser> because that is what ToListAsync will return. However in your view you are using this

    @model List<ContactManager.Models.UserModel>
    

    That means the view is expecting UserModel. Since you are passing a different type to the view it is raising the exception. To work around this the correct solution is to convert the IdentityUser instances to UserModel before passing that to the view. Unfortunately your existing model is not going to work. You are deriving from IdentityUser but you won't be able to create instances of that type nor can you magically associate them with a new UserModel instance. Instead you should accept (generally in the constructor or by using object initializer syntax) the IdentityUser you want to have the model represent. Convert each of the users before passing that on to the view.

    public class UserModel
    {
       //In general you should have a default constructor for models otherwise you run into binding issues
       public UserModel() { }
    
       //Converts a user to a model
       public UserModel ( IdentityUser user ) {
           //Set whatever properties you need
           UserName= user.UserName;
           Email  = user.Email;
       }
    
       //Expose whatever properties your view will need, just making some up here
       public string UserName { get; set; }
       public string Email { get; set; }
    }
    
    //Do the conversion from user to model
    var result = await db.Users.ToListAsync();
    var models = result.Select(x => new UserModel(x));
    return View(models);
    
    0 comments No comments

0 additional answers

Sort by: Most helpful

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.