How to seed the Authentication db in ASP NET MVC - asp.net-mvc

In which module do I do the seeding of the db? I want to add roles and users if they do not exist yet.
In NET Core I would use the startup file in this way:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
using (IServiceScope serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
var dbContext = serviceScope.ServiceProvider.GetService<ApplicationDbContext>();
var roleManager = serviceScope.ServiceProvider.GetService<RoleManager<IdentityRole>>();
var userManager = serviceScope.ServiceProvider.GetService<UserManager<User>>();
DbSeeder.Seed(Configuration, dbContext, roleManager, userManager);
}
}
and in my class DBSeeder:
public static class DbSeeder
{
public static void Seed(IConfiguration configuration,
ApplicationDbContext dbContext,
RoleManager<IdentityRole> roleManager,
UserManager<User> userManager)
{
if (!dbContext.Users.Any()) CreateUsers(configuration, dbContext, roleManager, userManager).GetAwaiter().GetResult();
}
private static async Task CreateUsers(IConfiguration configuration,
ApplicationDbContext dbContext,
RoleManager<IdentityRole> roleManager,
UserManager<User> userManager)
{
string role_Administrator = "Administrator";
string role_RegisteredUser = "RegisteredUser";
if (!await roleManager.RoleExistsAsync(role_Administrator))
{
await roleManager.CreateAsync(new IdentityRole(role_Administrator));
}
if (!await roleManager.RoleExistsAsync(role_RegisteredUser))
{
await roleManager.CreateAsync(new IdentityRole(role_RegisteredUser));
}
var user_Admin = new User()
{
SecurityStamp = Guid.NewGuid().ToString(),
UserName = "Admin",
Email = configuration["ContactUs"],
DisplayName = "Admin",
EmailConfirmed = true
};
if (await userManager.FindByNameAsync(user_Admin.UserName) == null)
{
await userManager.CreateAsync(user_Admin, "Pass4Admin");
await userManager.AddToRoleAsync(user_Admin, role_RegisteredUser);
await userManager.AddToRoleAsync(user_Admin, role_Administrator);
}
await dbContext.SaveChangesAsync();
}

Related

Some services are not able to be constructed Error while validating the service descriptor Lifetime: Scoped Unable to resolve service for type

my usermanager services is :
public class UserManagerService : IUserManagerService
{
private readonly UserManager<UserModel> userManager;
private readonly UserServiceHelper userServiceHelper;
public UserManagerService(UserManager<UserModel> _userManager)
{
this.userManager = _userManager;
userServiceHelper = new UserServiceHelper();
}
public async Task<bool> CreateUser(UserViewModel user)
{
try
{
var new_user = userServiceHelper.GetNewItems(user);
await userManager.CreateAsync(new_user);
return true;
}
catch(Exception e)
{
throw;
}
}
IUsermanagerServices interface is :
public interface IUsermanagerServices
{
Task<bool> CreateUser(UserViewModel user);
Task<bool> CreateUserBatch(List<UserViewModel> users);
Task<bool> DeleteUser(UserViewModel user);
}
And userapicontroller is :
[Route("api/[controller]")]
[ApiController]
public class UserApiController : ControllerBase
{
private readonly IUserManagerService userManager;
public UserApiController(IUserManagerService _userManager)
{
userManager = _userManager;
}
[HttpPost]
public async Task<IActionResult> Post([FromBody] List<UserViewModel> users)
{
try
{
var _result = await userManager.CreateUserBatch(users);
var _response = new ResponseModel<bool>()
{
Content = _result,
Message = "np"
};
return Ok(_response);
}
catch(Exception e)
{
var _response = new ResponseModel<bool>()
{
Content = false,
ExceptionMessage = e.Message,
HasError = true
}.ToString();
return Problem(_response);
}
}
service extension is :
public static void AddUserManagerServices(this IServiceCollection services)
{
services.AddScoped<IUserManagerService, UserManagerService>();
}
and program :
#region
builder.Services.AddUserManagerServices();
#endregion
var app = builder.Build();
in this last line i have exception
Some services are not able to be constructed (Error while validating the service
descriptor 'ServiceType: Lifetime: Scoped ImplementationType:
Unable to resolve service for type while attempting to activate)
how can i fix it ?

I am trying to seed users and user roles in asp.net but only the roles succeed

Hey This is probably a newbie question but I honestly can't find the problem after hours of searching for answers.
I am trying to create two roles and an admin user by seeding the database. I get no compilation errors but after running the application I couldn't login so I checked the database and noticed that the roles were created successfully but not the admin user.
Here is the class that I use for seeding:
public class Initialize
{
public static async Task InitializeAsync(ApplicationDbContext context, IServiceProvider serviceProvider)
{
var RoleManager = serviceProvider.GetRequiredService < RoleManager<IdentityRole>>();
UserManager<ApplicationUser> userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
string[] rolenames = { "Admin","Member"};
IdentityResult roleResult;
foreach (var roleName in rolenames) {
var roleExist = await RoleManager.RoleExistsAsync(roleName);
if (!roleExist)
{
roleResult = await RoleManager.CreateAsync(new IdentityRole(roleName));
}
}
string username = "admin";
string email = "admin#example.com";
string password = "Secret123";
string role = "Admin";
if (await userManager.FindByEmailAsync(username) == null)
{
ApplicationUser user = new ApplicationUser
{
UserName = username,
Email = email
};
IdentityResult result = await userManager
.CreateAsync(user, password);
if (result.Succeeded)
{
await userManager.AddToRoleAsync(user, role);
}
}
}
}
My ConfigureServices :
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// Add application services.
services.AddTransient<IEmailSender, EmailSender>();
services.AddMvc();
}
And Here is my Program.cs :
public class Program
{
public static void Main(string[] args)
{
var host = BuildWebHost(args);
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<ApplicationDbContext>();
Initialize.InitializeAsync(context, services).Wait();
}
catch(Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "Error seeding");
}
}
host.Run();
}
Any help is appreciated :)
Try look at userManager -> Store -> Users -> Results Views -> Message after access via serviceProvider.GetRequiredService. You can have some error message about it here.
If it contains a message:
"Cannot create a DbSet for 'ApplicationUser' because this type is not
included in the model for the context."
you must changed ApplicationContext class inherit from IdentityDbContext and it should be works fine.

Cannot create instance of repository object in action filter MVC

public interface IUserRepository : IBaseRepository<user>
{
user GetUser(int userId);
user Get(string Email);
}
public class UserRepository : BaseRepository<user>, IUserRepository
{
public UserRepository(IUnitOfWork unit) : base(unit)
{
}
public void Dispose()
{
throw new NotImplementedException();
}
public user GetUser(int userId)
{
return dbSet.Where(x => x.ID == userId).FirstOrDefault();
}
public user Get(string Email)
{
var obj = dbSet.Where(s => s.Email == Email).FirstOrDefault();
return obj;
}
}
And I am using the repository in my controller as below
public class AccountController : Controller
{
private readonly ApplicationUserManager UserManager;
private readonly ApplicationSignInManager SignInManager;
private readonly IAuthenticationManager AuthenticationManager;
private readonly IUnitOfWork uow;
private readonly UserRepository userrepo;
public AccountController(UserRepository _userrepo, ApplicationUserManager userManager, ApplicationSignInManager signInManager, IAuthenticationManager authenticationManager,IUnitOfWork _uow)
{
this.UserManager = userManager;
this.SignInManager = signInManager;
this.AuthenticationManager = authenticationManager;
this.uow = _uow;
userrepo = _userrepo;
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid )
{
var user = UserManager.FindByEmail(model.Email);
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
if (result)
{
var myUser = userRepo.Get(user.Id);
if (myUser.SubscriptionStatus == 1)
{
return RedirectToAction("ChangePassword", "Manage", new { ReturnUrl = returnUrl });
}
else
{
return RedirectToAction("Index","Admin");
}
}
}
}
And this is my action filter
public class CheckFirstLoginAttribute : ActionFilterAttribute
{
private readonly ApplicationUserManager UserManager;
private readonly IUnitOfWork uow;
private readonly UserRepository userrepo;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
string uName = HttpContext.Current.User.Identity.Name;
if (!string.IsNullOrEmpty(uName))
{
//var user = UserManager.FindByEmailAsync(uName);
//The above & below lines are not creating instance of the UserManager & UserRepository object, it is always null
user cUser= userrepo.GetUserId(uName);
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new
{
controller = "Manage",
action = "ChangePassword"
}));
}
}
}
And I am using Unity for the dependency injection
public class UnityConfig
{
#region Unity Container
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
public static IUnityContainer GetConfiguredContainer()
{
return container.Value;
}
#endregion
private static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<MyDbContext>();
container.RegisterType<UserRepository>();
container.RegisterType<IUnitOfWork, UnitOfWork>();
container.RegisterType<ApplicationDbContext>();
container.RegisterType<ApplicationSignInManager>();
container.RegisterType<ApplicationUserManager>();
container.RegisterType<HomeController>();
container.RegisterType<AccessCodeController>();
container.RegisterType<AdminController>();
container.RegisterType<IAuthenticationManager>(
new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication));
container.RegisterType<IUserStore<MyUser, int>, UserStore<MyUser, MyRole, int, MyUserLogin, MyUserRole, MyUserClaim>>(
new InjectionConstructor(typeof(ApplicationDbContext)));
}
}
How can I create the instance of the repository class and access the Get(string email) method. So that I can check the subscription status from the database.
I tried many ways and always failed to create the instance.
Kindly Help me.
Thanks
Tarak
public class CheckFirstLoginAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
string uName = HttpContext.Current.User.Identity.Name;
if (!string.IsNullOrEmpty(uName))
{
//Here is how I could get the instance of the repository
//I had to register the repository type and then
//I resolved it to obtain the object of the repository and
//access the methods in the repository
var container = new UnityContainer();
container.RegisterType<IUnitOfWork, UnitOfWork>();
container.RegisterType<UserRepository>();
UserRepository repo = container.Resolve<UserRepository>();
user cUser = repo.GetUserId(uName);
if (cUser.SubscriptionStatus == 1)
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new
{
controller = "Manage",
action = "ChangePassword"
}));
}
}
}
}

Asp.Net core MVC6 How to initially add roles in Identity 3

I've looked for this in Stackoverflow and so far it appears there are plenty of questions on adding roles in Identity 1 & 2 but its different in Identity 3.
I want to seed roles in the database. I have just two. I intended to use _roleManager which I have injected into the class. Thats fine. My problem is.. there doesnt appear to be any method to actually add a role.. Using CreateAsync is for adding the user to the role.. how do you code to add a role using "_userManager" or do you have to do it another way?
EDIT
Identity
In Identity RoleManager is for creating roles and UserManager is for adding users to roles.
This is an example to point you in the right direction. The code below is for creating a new role Administrator
if (!roleManager.RoleExists("Administrator"))
{
MyIdentityRole newRole = new MyIdentityRole("Administrator", "Administrators can do something with data");
roleManager.Create(newRole);
}
EDIT
Further, this is for adding a user to a role and this also an example:
\\assuming you test if the user has been assigned to the role "Administrator" before adding them to that role
if(RoleAdministrator == true){
userManager.AddToRole(User.Id, "Administrator");
}
public class SeedData
{
private const string _adminRoleName = "admin";
private string _adminEmail = "admin#demo.com";
private string _adminPassword = "P#ssw0rd!PK";
private string[] _roles = new string[] { _adminRoleName, "supervisor" };
private readonly RoleManager<IdentityRole<Guid>> _roleManager;
private readonly UserManager<ApplicationUser> _userManager;
public static async Task Run(IServiceProvider serviceProvider)
{
using (var serviceScope =serviceProvider
.GetRequiredService<IServiceScopeFactory>()
.CreateScope())
{
var instance = serviceScope.ServiceProvider.GetService<SeedData>();
await instance.Initialize();
var context = serviceScope.ServiceProvider.GetService<AppDbContext>();
if (!context.Products.Any())
{
// Seed Other entities Here
}
await context.SaveChangesAsync();
}
}
public SeedData(UserManager<ApplicationUser> userManager,
RoleManager<IdentityRole<Guid>> roleManager)
{
_roleManager = roleManager;
_userManager = userManager;
}
public async Task Initialize()
{
foreach (var role in _roles)
{
if (!await _roleManager.RoleExistsAsync(role))
{
await _roleManager.CreateAsync(new IdentityRole<Guid>(role));
}
}
var adminUsers = await _userManager.GetUsersInRoleAsync(_adminRoleName);
if (!adminUsers.Any())
{
var adminUser = new ApplicationUser()
{
Id = Guid.NewGuid(),
Email = _adminEmail,
UserName = _adminEmail
};
var result = await _userManager.CreateAsync(adminUser, _adminPassword);
if(result.Success)
{
await _userManager.AddToRoleAsync(adminUser, _adminRoleName);
}
}
}
}
In your Program.cs
public static void Main(string[] args)
{
var host = BuildWebHost(args);
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
SeedData.Run(services).Wait();
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "Error while seeding database.");
}
}
host.Run();
}
Might be helpful to someone :)

How to mock ApplicationUserManager from AccountController in MVC5

I am trying to write Unit Test for Register Method at AccountController
I am using moq and what is the correct way to mock ApplicationUserManager, ApplicationRoleManager and ApplicationSignInManager from Unit Test.
public AccountController(ApplicationUserManager userManager, ApplicationRoleManager roleManager, ApplicationSignInManager signInManager)
{
UserManager = userManager;
RoleManager = roleManager;
SignInManager = signInManager;
}
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
private ApplicationSignInManager _signInManager;
public ApplicationSignInManager SignInManager
{
get
{
return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
}
private set { _signInManager = value; }
}
private ApplicationRoleManager _roleManager;
public ApplicationRoleManager RoleManager
{
get
{
return _roleManager ?? HttpContext.GetOwinContext().Get<ApplicationRoleManager>();
}
set
{
_roleManager = value;
}
}
That is probably not exactly what you need, but take a look, maybe you'll get the idea.
AccountController.cs
[HttpGet]
[Route("register")]
[AllowAnonymous]
public ActionResult Register()
{
if (IsUserAuthenticated)
{
return RedirectToAction("Index", "Home");
}
return View();
}
public bool IsUserAuthenticated
{
get
{
return
System.Web.HttpContext.Current.User.Identity.IsAuthenticated;
}
}
AccountControllerTests.cs
[Test]
public void GET__Register_UserLoggedIn_RedirectsToHomeIndex()
{
// Arrange
HttpContext.Current = CreateHttpContext(userLoggedIn: true);
var userStore = new Mock<IUserStore<ApplicationUser>>();
var userManager = new Mock<ApplicationUserManager>(userStore.Object);
var authenticationManager = new Mock<IAuthenticationManager>();
var signInManager = new Mock<ApplicationSignInManager>(userManager.Object, authenticationManager.Object);
var accountController = new AccountController(
userManager.Object, signInManager.Object, authenticationManager.Object);
// Act
var result = accountController.Register();
// Assert
Assert.That(result, Is.TypeOf<RedirectToRouteResult>());
}
[Test]
public void GET__Register_UserLoggedOut_ReturnsView()
{
// Arrange
HttpContext.Current = CreateHttpContext(userLoggedIn: false);
var userStore = new Mock<IUserStore<ApplicationUser>>();
var userManager = new Mock<ApplicationUserManager>(userStore.Object);
var authenticationManager = new Mock<IAuthenticationManager>();
var signInManager = new Mock<ApplicationSignInManager>(userManager.Object, authenticationManager.Object);
var accountController = new AccountController(
userManager.Object, signInManager.Object, authenticationManager.Object);
// Act
var result = accountController.Register();
// Assert
Assert.That(result, Is.TypeOf<ViewResult>());
}
private static HttpContext CreateHttpContext(bool userLoggedIn)
{
var httpContext = new HttpContext(
new HttpRequest(string.Empty, "http://sample.com", string.Empty),
new HttpResponse(new StringWriter())
)
{
User = userLoggedIn
? new GenericPrincipal(new GenericIdentity("userName"), new string[0])
: new GenericPrincipal(new GenericIdentity(string.Empty), new string[0])
};
return httpContext;
}

Resources