Reputation: 1
PROBLEM:
System.InvalidCastException: 'Unable to cast object of type 'Microsoft.EntityFrameworkCore.Internal.InternalDbSet1[Microsoft.AspNetCore.Identity.IdentityUser
1[System.Int32]]' to type 'System.Linq.IQueryable`1[DAL.User]'.'
RELEVANT CODE:
...
public class SocialNetworkDbContext : IdentityDbContext<IdentityUser<int>, IdentityRole<int>, int>
...
public IQueryable<User> FindAll()
{
var allUsers = (IQueryable<User>)_socialNetworkDbContext.Users;
if (allUsers == null)
{
throw new NoRecordFoundException();
}
return allUsers;
TRIED:
public class SocialNetworkDbContext : IdentityDbContext<User>, IdentityRole<int>, int>
//no exception but this code breaks
var result = await _userManager.CreateAsync(user, model.Password);
await _userManager.AddToRoleAsync(user, model.Role);
//the same exception
3)
public IQueryable<User> FindAll()
{
var allUsers = (IQueryable<User>)(IEnumerable<User>)_socialNetworkDbContext.Users;
if (allUsers == null)
{
throw new NoRecordFoundException();
}
return allUsers;
// the same exception (unable to cast to IEnumerable). Cast to ICollection (unable to cast to ICollection)
Would be very thankful for any advice!!!
Upvotes: 0
Views: 6411
Reputation: 21353
From your code, it seems that the _socialNetworkDbContext.Users
was stored the IdentityUser, instead of User model, right? So, after query data from the Users table, you could use the following code to convert the query result:
public IQueryable<User> FindAll()
{
var allUsers = _socialNetworkDbContext.Users.Select(c => new User()
{
UserName = c.UserName,
Email = c.Email,
//... other properties
}).AsQueryable();
if (allUsers == null)
{
throw new NoRecordFoundException();
}
return allUsers;
}
Update
You can refer the following sample code:
Add an ApplicationUser class to customize the Identity User model:
public class ApplicationUser : IdentityUser<int>
{
public string CustomTag { get; set; }
}
Use the ApplicationUser type as a generic argument for the context:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, IdentityRole<int>, int>
{
public DbSet<ApplicationUser> ApplicationUsers { get; set; }
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
}
Update Pages/Shared/_LoginPartial.cshtml and replace IdentityUser with ApplicationUser:
@using Microsoft.AspNetCore.Identity
@using WebApp1.Areas.Identity.Data
@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager
Update the Startup.ConfigureServices
and replace IdentityUser
with ApplicationUser
:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDatabaseDeveloperPageExceptionFilter();
services.AddIdentity<ApplicationUser, IdentityRole<int>>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultUI()
.AddDefaultTokenProviders();
services.AddControllersWithViews();
}
Then, enable migration and generate the database.
After creating new user, the AspNetUser table data as below:
Create a UserViewModel and add the required properties:
public class UserViewModel
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Tag { get; set; }
}
Then, in the Controller, use the following code to query the user table:
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly ApplicationDbContext _context;
public HomeController(ILogger<HomeController> logger, ApplicationDbContext context)
{
_logger = logger;
_context = context;
}
public IActionResult Index()
{
var result = FindAll();
return View();
}
public IQueryable<UserViewModel> FindAll()
{
var allUsers = _context.Users.Select(c => new UserViewModel()
{
UserId = c.Id,
UserName = c.UserName,
Tag = c.CustomTag
});
//if (allUsers == null)
//{
// throw new NoRecordFoundException();
//}
return allUsers;
}
The result as below:
Upvotes: 1
Reputation: 58723
You should change your DbContext to use the actual user type:
public class SocialNetworkDbContext : IdentityDbContext<User, IdentityRole<int>, int>
{
}
If you have a class for the roles, you should use that as the generic type argument as well. This way you won't need any type casts.
Upvotes: 2
Reputation: 1
change your code :
public async Task<List<User>> GetAllUsers()
{
var allUsers = await _socialNetworkDbContext.Users.ToListAsync();
if (allUsers == null)
{
throw new NoRecordFoundException();
}
return allUsers;
}
Upvotes: -1