I'm building an .NET MVC application with Identity for user login. The application has four Layers.
- Web/UI layer, has reference to my domain and service layers
- Domain layer, has no references
- Service layer, has reference to my data and domain layers
- Data layer, has reference to my domain layer
I want my AppUser class to have a reltionship to one of my entities in my data layer, Company.
The AppUser class is residing in my domain layer and it is inheriting from IdentityUser. The reason i placed my AppUser class in my domain layer is beacuse i need to have access to it from my Web/UI layer where the IdentityConfig needs the class.
But when i now want to add a relationhip to an entity in my data layer things got tricky for me.
AppUser Class as i want it to look:
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using System.Security.Claims;
using System.Threading.Tasks;
namespace ITKA.Domain.Classes
{
public class AppUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string ContactNumber { get; set; }
public int CompanyId { get; set; }
public Company Company { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<AppUser> manager)
{
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
return userIdentity;
}
public void Dispose()
{
}
}
}
Company Class as it looks:
using ITKA.Data.Interfaces;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace ITKA.Data.Entities
{
[Table("CompanyTbl")]
public class Company : IEntity
{
[Key]
public int Id { get; set; }
[StringLength(100)]
public string CompanyName { get; set; }
public virtual ICollection<InventoryItem> InventoryItems { get; set; }
}
}
IdentityConfig Class as it looks
using System;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using ITKA.Domain.Classes;
using ITKA.Domain.Interfaces;
namespace ITKA.Web
{
public class AppUserManager : UserManager<AppUser>
{
public AppUserManager(IUserStore<AppUser> userStore)
: base(userStore)
{
}
public static AppUserManager Create(IdentityFactoryOptions<AppUserManager> options, IOwinContext context)
{
var userStore = new UserStore<AppUser>((IdentityDbContext<AppUser>)context.Get<IITKAContext>());
var manager = new AppUserManager(userStore);
manager.UserValidator = new UserValidator<AppUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 8,
RequireNonLetterOrDigit = false,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true
};
manager.UserLockoutEnabledByDefault = false;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
return manager;
}
}
public class AppSignInManager : SignInManager<AppUser, string>
{
public AppSignInManager(AppUserManager userManager,
IAuthenticationManager authManager)
: base(userManager, authManager) { }
public static AppSignInManager Create
(IdentityFactoryOptions<AppSignInManager> options, IOwinContext context)
{
return new AppSignInManager(context.Get<AppUserManager>(),
context.Authentication);
}
}
public class AppRoleManager : RoleManager<IdentityRole>
{
public AppRoleManager(RoleStore<IdentityRole> roleStore)
: base(roleStore) { }
public static AppRoleManager Create(IOwinContext context)
{
var roleStore = new RoleStore<IdentityRole>
((IdentityDbContext<AppUser>)context.Get<IITKAContext>());
return new AppRoleManager(roleStore);
}
}
}
I dont know how to be able to place the AppUser class in my data layer so that IdentityConfig can be able to "reach" it since those layers has no reference to each other.
I tried to move my AppUser class to my data layer and made it use an interface i added to my domain layer, IAppUser. I changed IdentityConfig to use my interface instead of my class but it gave me alot of squiggliez.
First issue i ran into was that there where no implicit conversion between IAppUser and IUser, so i made my IAppUser interface inherit from IUser and it solved some problems in the IdentityConfig class.
But in some places it still complained that there is no implicit conversion between IAppUser and the class IdentityUser. I cant make my interface inherit from a class so there that experiment ended.
I dont know if there is a way to add a relationship to my AppUser class to an entity that is in my data layer through an interface in my domain layer maybe? This feels like it wouldn't work to me because i think that EF needs to know implicitly what class/entity it makes a relationship to. And since many diffrent classes kan inherit from an interface this feels impossible to me. Am i wrong?
Or could i have in my AppUser class a property with an interface and EF would create an relationship? If my Company class would use an interface named ICompany and my AppUser class have a property like:
public ICompany Company { get; set; }
would it create a relationship to Company?
I had trouble when IdentityConfig needed my DbContext class that also resides in my data layer but that problem i was able to solve by using an interface in my domain layer.
Im really stuck here and i dont know how to solve this problem. I am thankful for any help.