I have two models/tables, one is User and the other is role the relationship is one Role can have many users. I am trying to loop through the data in the user model navigation property but i am getting an error that its returning null.
User model
public class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int User_Id { get; set; }
[Required]
[Display(Name ="User Name")]
public string User_Name { get; set; }
[Required(ErrorMessage = "The Field Is Required")]
[MaxLength(10, ErrorMessage = " Please Enter A Valid Input")]
public string Password { get; set; }
//Nav
[ForeignKey("RoleId")]
[Display(Name ="User Role:")]
public int RoleId { get; set;}
public Role Role { get; set; }
}
Role Model
public class Role
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Role_id { get; set; }
[Required(ErrorMessage ="This field is required")]
[Display(Name ="Role Name :")]
public string RoleType { get; set; }
//nav
public List<User> Users { get; set; }
}
Controller action Method:
public async Task<IActionResult> Index()
{
var viewModel = await userRepository.GetAllUsersAlongWithRolesAsync();
//var viewModel = await baseRepository.GetAllObjectsAsync();
return View("Index",viewModel);
}
Updates: UserRepository that inherited from the IBaseRepository
public class UserRepository : BaseRepository<User>, IUserRepository
{
private readonly ApplicationDbContext _Context;
public UserRepository(ApplicationDbContext context):base (context)
{
_Context = context;
}
public async Task <IEnumerable<User>> GetAllUsersAlongWithRolesAsync()
{
var getUsers = await _Context.Users.Include(u => u.Role).ToListAsync();
return getUsers;
}
}
In the User controller for injecting:
// injection
private readonly IBaseRepository<User> baseRepository;
private readonly IBaseRepository<Role> roleRepository;
private readonly IUserRepository userRepository;
public UserController(IBaseRepository<User> _baseRepository, IBaseRepository<Role> _roleRepository, IUserRepository userRepository)
{
baseRepository = _baseRepository;
this.roleRepository = _roleRepository;
this.userRepository = userRepository;
}
Since your method GetAllObjectsAsync is so generic, you probably won't be able to add the .Include() you need.
I'd suggest a separate method GetAllUsers() to your repository - possibly the concrete UserRepository, if you have that:
public async Task<IEnumerable<User>> GetAllUsersAsync()
{
var getUsers = await _Context.Users.Include(u => u.Role).ToListAsync();
return getUsers;
}
Related
Good Day. I am suffering a problem with asp.net identity. I am getting error at this line:
var user = await _userManager.FindByEmailAsync(Input.Email);
the error is : (Microsoft.Data.SqlClient.SqlException (0x80131904): Invalid object name 'AspNetUsers'.
)
For your kind information, I have added a model ApplicationUser
public class ApplicationUser : IdentityUser
{
public string UserID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string PhoneNo { get; set; }
//============Linked Table==================
[Display(Name = "ব্যাবহারকারীর ধরণ")]
[ForeignKey("UserType")]
public int UserTypeId { get; set; }
public UserType UserType { get; set; }
[Display(Name = "ব্যাবহারকারীর শাখা")]
[ForeignKey("Department")]
public int DepartmentId { get; set; }
public Department Department { get; set; }
//============Image Url====================
[Display(Name = "ব্যাবহার কারীর ছবি")]
public string UserImageURL { get; set; }
}
here is my application db context:
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
here is my startup.cs file
services.AddIdentity<ApplicationUser, IdentityRole>()
// adds UserStore and RoleStore for Usermanager and RoleManager
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultUI()
// adds a provider that generates unique keys and hashes for things like forgot password links, phone verification etc
.AddDefaultTokenProviders();
for register.cs and login.cs
private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly ILogger<LoginModel> _logger;
private readonly IEmailSender _emailSender;
public LoginModel(SignInManager<ApplicationUser> signInManager,
ILogger<LoginModel> logger,
UserManager<ApplicationUser> userManager,
IEmailSender emailSender)
{
_userManager = userManager;
_signInManager = signInManager;
_emailSender = emailSender;
_logger = logger;
}
can any body suggest me what is the problem... I am stuck on this line
var user = await _userManager.FindByEmailAsync(Input.Email);
thanks in advance
Moseur
My dbContext return null, when I want get list of user in Index View. This list are from my database AspNetUsers table, which has been generate by identity. I can get other my database table list.
There is my ApplicationDbContext
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<ProductCategory> ProductCategories { get; set; }
public DbSet<ProductBrand> ProductBrands { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<ApplicationUser> ApplicationUsers { get; set; }
public DbSet<Address> Address { get; set; }
public DbSet<Recipe> Recipes { get; set; }
public DbSet<Order> Orders { get; set; }
public DbSet<Order_detail> Order_Details { get; set; }
}
There is my UserController
[Area("Admin")]
public class UserController : Controller
{
UserManager<IdentityUser> _userManager;
private ApplicationDbContext _db;
public UserController(UserManager<IdentityUser> userManager, ApplicationDbContext db)
{
_userManager = userManager;
_db = db;
}
public IActionResult Index()
{
return View(_db.ApplicationUsers.ToList());
}
}
There is my ApplicationUser.Model, which inherit IdendityUser
public class ApplicationUser : IdentityUser
{
public string Name { get; set; }
public string Surname { get; set; }
public ICollection<Recipe> Products { get; set; }
public ICollection<Order> Orders { get; set; }
}
I don't know how you register ApplicationDbContext and Identity framework on your ASP.NET Core MVC application because you didn't show them on the question.
There are couple problems in your code.
First, if you have a custom IdentityUser, like the ApplicationUser you have, you would have to use the generic version of IdentityDbContext:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
...
}
You would need to use the matching generic version of IdentityDbContext if you have any of following:
Custom IdentityUser
Custom IdentityRole
Custom primary key
All 7 classes, user and role, plus IdentityUserRole, IdentityUserClaim, IdentityRoleClaim, IdentityUserLogin, and IdentityUserToken
After you register your custom class with IdentityDbContext, you don't need to put the class as one of the DbSet<> there:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
...
public DbSet<ProductCategory> ProductCategories { get; set; }
public DbSet<ProductBrand> ProductBrands { get; set; }
public DbSet<Product> Products { get; set; }
// public DbSet<ApplicationUser> ApplicationUsers { get; set; }
public DbSet<Address> Address { get; set; }
public DbSet<Recipe> Recipes { get; set; }
public DbSet<Order> Orders { get; set; }
public DbSet<Order_detail> Order_Details { get; set; }
}
You would also need to use the generic version of AddIdentity<TUser>, AddDefaultIdentity<TUser>, or AddIdentityCore<TUser> in your Startup.cs, depending on what you need:
AddDefaultIdentity = AddIdentity + AddDefaultTokens + AddDefaultUI
You didn't specify what version of ASP.NET Core Identity you're using so I don't exactly know which one you use, but the following is how I registered it:
services.AddIdentity<ApplicationUser, ApplicationRole>(options =>
{
options.User.RequireUniqueEmail = ...;
...
})
.AddEntityFrameworkStores<ApplicationDbContext>();
I have all 7 classes customized as well as change the primary key from string to Guid.
Lastly, to use the dependency injected UserManager and SignInManager, you would need to correct generic version of them as well:
[Area("Admin")]
public class UserController : Controller
{
private readonly UserManager<ApplicationUser> _userManager;
public UserController(UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
}
public IActionResult Index()
{
// Get the user list
var users = _userManager.Users.ToList();
// Build your view model to define what your UI only needs, not just passing
// everything to it
var vm = new UserManagementListViewModel
{
Users = users.Select(x => new UserViewModel
{
UserId = x.Id,
UserSurname = x.Surname,
ProductCount = x.Products.Count(),
OrderCount = x.Orders.Count()
})
};
return View(vm);
}
}
I write a custom IdentityUser which is AuthUser.
public class AuthUser : IdentityUser
{
public int StudentsId { get; set; }
public virtual Students StudentProfile { get; set; }
public int InstructorId { get; set; }
public virtual Instructor InstructorProfile { get; set; }
public bool IsStudent { get; set; }
public bool IsInstructor { get; set; }
}
The context is okay as you can see
public class LmsContext : IdentityDbContext<AuthUser> //DbContext
{
}
The startup.cs is all setup
services.AddDbContext<LmsContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("UCIPrimarySchool"))
);
services.AddDefaultIdentity<AuthUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<LmsContext>();
services.AddControllersWithViews();
services.AddRazorPages();
But when I try to login I get the following error.
An unhandled exception occurred while processing the request.
SqlException: Invalid object name 'AspNetUsers'.
Microsoft.Data.SqlClient.SqlCommand+<>c.<ExecuteDbDataReaderAsync>b__169_0(Task<SqlDataReader> result)
Why is is not querying the extended AuthUser but instead goes for the none existing table AspNetUsers?
First, you should clarify your relationship and then migrations and updated the database correctly.
Change your AuthUser like this:
public class AuthUser : IdentityUser
{
public virtual Students StudentProfile { get; set; }
public virtual Instructor InstructorProfile { get; set; }
public bool IsStudent { get; set; }
public bool IsInstructor { get; set; }
}
In your Context:
public DbSet<Students> Students { get; set; }
public DbSet<Instructor> Instructor { get; set; }
Migration and update:
After successfully updating the database, you need to change your View/Shared/_LoginPartial code:
#inject SignInManager<IdentityUser> SignInManager
#inject UserManager<IdentityUser> UserManager
to
#inject SignInManager<AuthUser> SignInManager
#inject UserManager<AuthUser> UserManager
Then
Select your LmsContext Add
Then start your app,and login.
One user can be a member of many projects while a project can have multiple members.
ASP.NET Identity ApplicationUser
public class ApplicationUser : IdentityUser
{
[Display(Name = "Projekt")]
public virtual ICollection<Project> Projects { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
return userIdentity;
}
}
My Project:
[Table("Projects")]
public class Project : IValidatableObject
{
[Key]
public int ID { get; set; }
[Required, StringLength(128), Display(Name = "Projektname"), Index(IsUnique = true)]
public string Name { get; set; }
// working one-to-many relation
[Display(Name = "Projektleiter")]
public string LeaderID { get; set; }
[ForeignKey("LeaderID"), Display(Name = "Projektleiter")]
public virtual ApplicationUser ApplicationUser { get; set; }
// many-to-many relation gets ignored
[Display(Name = "Mitarbeiter")]
public virtual ICollection<ApplicationUser> ApplicationUsers { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
return new List<ValidationResult>();
}
}
No Many-to-Many table is created. The whole relation gets ignored. But the LeaderID thing is working ...
Can somebody tell me what I am missing here? (I googled the hell out of it, I deleted the whole database multiple times, I tried everything I found, no luck ...)
I would keep the ApplicationUser entity separated from whatever logic you have with the project and create another entity called Person.
public class Person
{
//Constuctor : always intantiate lists in ctor
public Person()
{
Projects = new List<Project>();
}
public int Id { get; set; }
public string IdentityId { get; set; } //gets guid from AppUser table
public ApplicationUser Identity { get; set; } // navigation property
public List<Project> Projects { get; set; }
//public int ProjectId {get; set;}//-----optional
}
so in projects know we do the same thing:
[Table("Projects")]
public class Project : IValidatableObject
{
//Constuctor : always intantiate lists in ctor
public Project()
{
Persons = new List<Person>();
}
[Key]
public int ID { get; set; }
[Required, StringLength(128), Display(Name = "Projektname"), Index(IsUnique = true)]
public string Name { get; set; }
public string PersonId { get; set; } //nav property
public List<Persons> Persons { get; set; }
public Person Person { get; set; } //context will be aware that this is fk
[Display(Name = "Projektleiter")]
public string LeaderID { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
return new List<ValidationResult>();
}
}
add db sets for both entities in the dbcontext class.
Now you want to get a person with a list of projects and vice versa. For that we use the include:
var x = myContext.Persons.Include(x => x.Projects);
var d = x.ToList();
//you can use the applicationUser entity instead of person but bad things happen as the project grows.
I want to assign a list of stores to a particular client, based on the Identity Model in MVC 5. I want to be able to register a user/client using the default registration in the MVC 5 example code and be able to add a store, then assign the store to the user.
I'm having trouble being able to create a working viewmodel that incorporates the idenity model with a new list.
Here is what I have so far:
Model:
public class ApplicationUser : IdentityUser
{
//[Required]
[Display(Name = "Client/Company Name")]
public string ClientName { get; set; }
public List<Store> Stores { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
I tried to add to the existing default dbcontext:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public DbSet<Store> Stores { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
My controller blows up when I try to set my store clientname to the user clientname. Clientname or any other property is unavailable for ApplicationUser.
private ApplicationDbContext db = new ApplicationDbContext();
// GET: Stores
public ActionResult Index(ClientStoreViewModel viewModel)
{
var clients = from s in db.Stores
join c in db.Users
on s.ClientName equals u.ClientName
select new ClientStoreViewModel() { Stores = s, Users = u };
return View(clients);
}
Store class:
public class Store
{
public int Id { get; set; }
//public int ClientId { get; set; }
[Display(Name = "Client Name")]
public string ClientName { get; set; }
[Display(Name = "Store Name")]
public string Brand { get; set; }
[Display(Name = "Store Number")]
public string StoreNumber { get; set; }
[Display(Name="Store Login URL")]
public string LoginURL { get; set; }
}
Finally my viewmodel:
public class ClientStoreViewModel
{
public ApplicationUser Users { get; set; }
public Store Stores { get; set; }
public ClientStoreViewModel()
{
Stores = new Store();
Users = new ApplicationUser();
}
}