Testing Specific Method Calls with Parameters using Moq - moq

I'm trying to write a Unit Test with Moq to verify that a Registration was successful. My Test is as follows:
[TestMethod()]
public void RegisterTest()
{
//Arrange
var MockRepo = new Mock<IDataRepo>() ;
RegisterModel model = new RegisterModel
{
ConfirmPassword = "SamePassword",
Email = "myemail#address.com",
FirstName = "MyFirstName",
LastName = "MyLastName",
MiddleName = "MyMiddleName",
Password = "SamePassword"
};
MockRepo.Setup(ctx => ctx.Add(model)).Verifiable("Nothing was added to the Database");
//Act
AccountController target = new AccountController(MockRepo.Object);
//Assert
ActionResult actual = target.Register(model);
MockRepo.Verify(ctx => ctx.Add(It.IsAny<RegisterModel>()));
Assert.IsInstanceOfType(actual, typeof(ViewResult));
}
But it fails with the following Error
Expected invocation on the mock at least once, but was never performed: ctx => ctx.Add(It.IsAny())
However, When I debugged the Test Method, I noticed that the Add(T) method was actually called.
The MOQ dll version is v4.0
UPDATE
Account Controller:
public class AccountController : Controller
{
private IDataRepo _repo;
public AccountController(IDataRepo Repo)
{
_repo = Repo;
}
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
User user = _repo.Users.Where(u => u.Email == model.Email).FirstOrDefault();
if (user == null)
{
_repo.Add(new User
{
Email = model.Email,
Password = model.Password,
FirstName = model.FirstName,
LastName = model.LastName,
MiddleName = model.MiddleName
});
return View("RegistrationSuccess");
}
else
{
ModelState.AddModelError("UserExists", "This Email already Exists");
}
}
return View(model);
}
}

Your problem is that your Mock expects a RegisterModel instance
RegisterModel model = new RegisterModel
{
ConfirmPassword = "SamePassword",
Email = "myemail#address.com",
FirstName = "MyFirstName",
LastName = "MyLastName",
MiddleName = "MyMiddleName",
Password = "SamePassword"
};
MockRepo.Setup(ctx => ctx.Add(model))
but the Add method gets called with an instance of the User class
_repo.Add(new User
{
Email = model.Email,
Password = model.Password,
FirstName = model.FirstName,
LastName = model.LastName,
MiddleName = model.MiddleName
});
So, one way to get around this is to setup the mock to accept a User instance.
RegisterModel model = new RegisterModel
{
ConfirmPassword = "SamePassword",
Email = "myemail#address.com",
FirstName = "MyFirstName",
LastName = "MyLastName",
MiddleName = "MyMiddleName",
Password = "SamePassword"
};
User expected = new User
{
Email = model.Email,
Password = model.Password,
FirstName = model.FirstName,
LastName = model.LastName,
MiddleName = model.MiddleName
};
MockRepo.Setup(ctx => ctx.Add(expected))

I discovered an easier way to do it. Rather than generate your own User object you could call It.IsAny<User>() and the test would run just fine. so my unit test now becomes..
//Arrange
var MockRepo = new Mock<IDataRepo>() ;
var MockMembership = new Mock<IMembership>();
RegisterModel model = new RegisterModel
{
ConfirmPassword = "SamePassword",
Email = "myemail#address.com",
FirstName = "MyFirstName",
LastName = "MyLastName",
MiddleName = "MyMiddleName",
Password = "SamePassword"
};
MockRepo.Setup(ctx => ctx.Add(It.IsAny<User>())).Verifiable("Nothing was added to the Database");
//Act
AccountController target = new AccountController(MockRepo.Object, MockMembership.Object);
//Assert
ActionResult actual = target.Register(model);
MockRepo.Verify(ctx => ctx.Add(It.IsAny<User>()));
Assert.IsInstanceOfType(actual, typeof(ViewResult));

Related

ASP.NET Razor Page Select List Loses Data after Server-Side Validation Failed

I am using .NET Identity for authentication and authorization.
For my registration page, I added two selectListItem properties in the InputModel class for dropdown lists.
The problem is, when the server-side validation failed, the dropdown lists lost their data as the page reloaded. Other basic data are saved.
I consulted several old posts on how to repopulate the dropdown list but still can't solve the problem. I don't know what exactly is being executed after the return Page() is called.
Thanks in advance.
Here's page model and methods:
public class InputModel
{
......
[Required]
public string Name { get; set; }
......
[ValidateNever]
public IEnumerable<SelectListItem> RoleList { get; set; }
[ValidateNever]
public IEnumerable<SelectListItem> CompanyList { get; set; }
}
public async Task OnGetAsync(string returnUrl = null)
{
......
......
Input = new InputModel()
{
RoleList = _roleManager.Roles.Select(x => x.Name).Select(i => new SelectListItem
{
Text = i,
Value = i
}),
CompanyList = _unitOfWork.Company.GetAll().Select(i => new SelectListItem
{
Text = i.Name,
Value = i.Id.ToString()
})
};
}
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
......
if (ModelState.IsValid)
{
var user = CreateUser();
await _userStore.SetUserNameAsync(user, Input.Email, CancellationToken.None);
await _emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None);
user.StreetAddress = Input.StreetAddress;
user.City = Input.City;
user.State = Input.State;
user.PostalCode = Input.PostalCode;
user.Name = Input.Name;
user.PhoneNumber = Input.PhoneNumber;
if(Input.Role == SD.Role_User_Comp)
{
user.CompanyId = Input.CompanyId;
}
var result = await _userManager.CreateAsync(user, Input.Password);
if (result.Succeeded)
{
......
......
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
// If we got this far, something failed, redisplay form
return Page();
}
You can try to set RoleList and CompanyList into OnPostAsync:
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
......
if (ModelState.IsValid)
{
var user = CreateUser();
await _userStore.SetUserNameAsync(user, Input.Email, CancellationToken.None);
await _emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None);
user.StreetAddress = Input.StreetAddress;
user.City = Input.City;
user.State = Input.State;
user.PostalCode = Input.PostalCode;
user.Name = Input.Name;
user.PhoneNumber = Input.PhoneNumber;
if(Input.Role == SD.Role_User_Comp)
{
user.CompanyId = Input.CompanyId;
}
var result = await _userManager.CreateAsync(user, Input.Password);
if (result.Succeeded)
{
......
......
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
RoleList = _roleManager.Roles.Select(x => x.Name).Select(i => new SelectListItem
{
Text = i,
Value = i
});
CompanyList = _unitOfWork.Company.GetAll().Select(i => new SelectListItem
{
Text = i.Name,
Value = i.Id.ToString()
});
// If we got this far, something failed, redisplay form
return Page();
}
Also suffering from the same problem for the last few days. I solved it by using Yiyi You's method. Though I made a different function for assigning values to the Properties (in your case RoleList and CompanyList) then call it in both OnPostAsync and OnGetAsync

Name cannot be null or empty

I am trying to use identity with DB first and I followed the this link https://www.youtube.com/watch?v=elfqejow5hM. I am getting an error "Name cannot be null or empty." I don't have any column Name. And also does not called the "OnModelCreating".
this is my application user class
public class MyUser : IdentityUser<long, MyLogin, MyUserRole, MyClaim>
{
public string UserName { get; set; }
}
public class MyUserRole : IdentityUserRole<long> { }
public class MyRole : IdentityRole<long, MyUserRole> { }
public class MyClaim : IdentityUserClaim<long> { }
public class MyLogin : IdentityUserLogin<long> { }
this is my onmodelcreating code
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<MyUser>().ToTable("AspNetUser");
modelBuilder.Entity<MyUserRole>().ToTable("AspNetRole");
modelBuilder.Entity<MyRole>().ToTable("AspNetRole");
modelBuilder.Entity<MyClaim>().ToTable("AspNetUserClaim");
modelBuilder.Entity<MyLogin>().ToTable("AspNetUserLogin");
modelBuilder.Entity<MyUser>().Property(r => r.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<MyRole>().Property(r => r.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<MyClaim>().Property(r => r.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
and my register post method is
var manager = HttpContext.GetOwinContext().GetUserManager<MyUser>();
var user = new MyUser()
{
Email = model.Email,
EmailConfirmed = false,
PhoneNumberConfirmed = false,
TwoFactorEnabled = false,
LockoutEndDateUtc = DateTime.Now,
LockoutEnabled = false,
AccessFailedCount = 0,
UserName = model.userName
};
IdentityResult result = await UserManager.CreateAsync(user, model.Password);
Can any one help me the cause for the error.

How to Seed Users and Roles with Code First Migration using Identity ASP.NET Core

I have created a new clean asp.net 5 project (rc1-final). Using Identity Authentication I just have the ApplicationDbContext.cs with the following code:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
protected override void OnModelCreating(ModelBuilder builder)
{
// On event model creating
base.OnModelCreating(builder);
}
}
Please note ApplicationDbContext use IdentityDbContext and not DbContext.
There is any IdentityConfig.cs. Where i need to put the classic protected override void Seed to create role and user if it does not exist?
My way of doing this is to create a class in models namespace.
public class SampleData
{
public static void Initialize(IServiceProvider serviceProvider)
{
var context = serviceProvider.GetService<ApplicationDbContext>();
string[] roles = new string[] { "Owner", "Administrator", "Manager", "Editor", "Buyer", "Business", "Seller", "Subscriber" };
foreach (string role in roles)
{
var roleStore = new RoleStore<IdentityRole>(context);
if (!context.Roles.Any(r => r.Name == role))
{
roleStore.CreateAsync(new IdentityRole(role));
}
}
var user = new ApplicationUser
{
FirstName = "XXXX",
LastName = "XXXX",
Email = "xxxx#example.com",
NormalizedEmail = "XXXX#EXAMPLE.COM",
UserName = "Owner",
NormalizedUserName = "OWNER",
PhoneNumber = "+111111111111",
EmailConfirmed = true,
PhoneNumberConfirmed = true,
SecurityStamp = Guid.NewGuid().ToString("D")
};
if (!context.Users.Any(u => u.UserName == user.UserName))
{
var password = new PasswordHasher<ApplicationUser>();
var hashed = password.HashPassword(user,"secret");
user.PasswordHash = hashed;
var userStore = new UserStore<ApplicationUser>(context);
var result = userStore.CreateAsync(user);
}
AssignRoles(serviceProvider, user.Email, roles);
context.SaveChangesAsync();
}
public static async Task<IdentityResult> AssignRoles(IServiceProvider services, string email, string[] roles)
{
UserManager<ApplicationUser> _userManager = services.GetService<UserManager<ApplicationUser>>();
ApplicationUser user = await _userManager.FindByEmailAsync(email);
var result = await _userManager.AddToRolesAsync(user, roles);
return result;
}
}
To run this code on startup. In Startup.cs at end of configure method just after route configuration add following code as Stafford Williams said before.
SampleData.Initialize(app.ApplicationServices);
You can seed Users and Roles in OnModelCreating() method inside IdentityDbContext.cs file as shown below. Notice that the keys have to be predefined to avoid seeding new users and roles everytime this method is executed.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//Seeding a 'Administrator' role to AspNetRoles table
modelBuilder.Entity<IdentityRole>().HasData(new IdentityRole {Id = "2c5e174e-3b0e-446f-86af-483d56fd7210", Name = "Administrator", NormalizedName = "ADMINISTRATOR".ToUpper() });
//a hasher to hash the password before seeding the user to the db
var hasher = new PasswordHasher<IdentityUser>();
//Seeding the User to AspNetUsers table
modelBuilder.Entity<IdentityUser>().HasData(
new IdentityUser
{
Id = "8e445865-a24d-4543-a6c6-9443d048cdb9", // primary key
UserName = "myuser",
NormalizedUserName = "MYUSER",
PasswordHash = hasher.HashPassword(null, "Pa$$w0rd")
}
);
//Seeding the relation between our user and role to AspNetUserRoles table
modelBuilder.Entity<IdentityUserRole<string>>().HasData(
new IdentityUserRole<string>
{
RoleId = "2c5e174e-3b0e-446f-86af-483d56fd7210",
UserId = "8e445865-a24d-4543-a6c6-9443d048cdb9"
}
);
}
As of the time of this writing, there is no plug in place for seeding the database, but you can create a class and add it to your container to do the same thing on app start, here is how I've done it, first create a class:
public class YourDbContextSeedData
{
private YourDbContext _context;
public YourDbContextSeedData(YourDbContext context)
{
_context = context;
}
public async void SeedAdminUser()
{
var user = new ApplicationUser
{
UserName = "Email#email.com",
NormalizedUserName = "email#email.com",
Email = "Email#email.com",
NormalizedEmail = "email#email.com",
EmailConfirmed = true,
LockoutEnabled = false,
SecurityStamp = Guid.NewGuid().ToString()
};
var roleStore = new RoleStore<IdentityRole>(_context);
if (!_context.Roles.Any(r => r.Name == "admin"))
{
await roleStore.CreateAsync(new IdentityRole { Name = "admin", NormalizedName = "admin" });
}
if (!_context.Users.Any(u => u.UserName == user.UserName))
{
var password = new PasswordHasher<ApplicationUser>();
var hashed = password.HashPassword(user, "password");
user.PasswordHash = hashed;
var userStore = new UserStore<ApplicationUser>(_context);
await userStore.CreateAsync(user);
await userStore.AddToRoleAsync(user, "admin");
}
await _context.SaveChangesAsync();
}
Register the type in ConfigureServices method of your Startup.cs class:
services.AddTransient<YourDbContextSeedData>();
Next pass the YourDbContextSeedData class to the Configure method of your Startup.cs class and use it:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, YourDbContextSeedData seeder)
{
seeder.SeedAdminUser();
}
If you have async issues, try the following code:
protected override void Seed(ApplicationDbContext context)
{
// This method will be called after migrating to the latest version.
string[] roles = new string[] { "Admin", "User" };
foreach (string role in roles)
{
if (!context.Roles.Any(r => r.Name == role))
{
context.Roles.Add(new IdentityRole(role));
}
}
//create user UserName:Owner Role:Admin
if (!context.Users.Any(u => u.UserName == "Owner"))
{
var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
var user = new ApplicationUser
{
FirstName = "XXXX",
LastName = "XXXX",
Email = "xxxx#example.com",
UserName = "Owner",
PhoneNumber = "+111111111111",
EmailConfirmed = true,
PhoneNumberConfirmed = true,
SecurityStamp = Guid.NewGuid().ToString("D"),
PasswordHash = userManager.PasswordHasher.HashPassword("secret"),
LockoutEnabled = true,
};
userManager.Create(user);
userManager.AddToRole(user.Id, "Admin");
}
context.SaveChanges();
}
In aspnetcore there is the concept of IHostedService. This makes it possible to run async background Task.
The solution of #hamid-mosalla could be made async and called from an IHostedService implementation.
Seed class implementation could be something like
public class IdentityDataSeeder
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly RoleManager<IdentityRole> _roleManager;
public IdentityDataSeeder(
UserManager<ApplicationUser> userManager,
RoleManager<IdentityRole> roleManager)
{
_userManager = userManager;
_roleManager = roleManager;
}
public async Task SeedAsync()
{
var superAdminRole = new IdentityRole
{
Id = "cac43a6e-f7bb-4448-baaf-1add431ccbbf",
Name = "SuperAdmin",
NormalizedName = "SUPERADMIN"
};
await CreateRoleAsync(superAdminRole);
var superAdminUserPassword = "P#ssword1";
var superAdminUser = new ApplicationUser
{
Id = "b8633e2d-a33b-45e6-8329-1958b3252bbd",
UserName = "admin#example.nl",
NormalizedUserName = "ADMIN#EXAMPLE.NL",
Email = "admin#example.nl",
NormalizedEmail = "ADMIN#EXAMPLE.NL",
EmailConfirmed = true,
};
await CreateUserAsync(superAdminUser, superAdminUserPassword);
var superAdminInRole = await _userManager.IsInRoleAsync(superAdminUser, superAdminRole.Name);
if (!superAdminInRole)
await _userManager.AddToRoleAsync(superAdminUser, superAdminRole.Name);
}
private async Task CreateRoleAsync(IdentityRole role)
{
var exits = await _roleManager.RoleExistsAsync(role.Name);
if (!exits)
await _roleManager.CreateAsync(role);
}
private async Task CreateUserAsync(ApplicationUser user, string password)
{
var exists = await _userManager.FindByEmailAsync(user.Email);
if (exists == null)
await _userManager.CreateAsync(user, password);
}
}
This can be called from an IHostedService:
public class SetupIdentityDataSeeder : IHostedService
{
private readonly IServiceProvider _serviceProvider;
public SetupIdentityDataSeeder(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
using (var scope = _serviceProvider.CreateScope())
{
var seeder = scope.ServiceProvider.GetRequiredService<IdentityDataSeeder>();
await seeder.SeedAsync();
}
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
Startup would look like:
public void ConfigureServices(IServiceCollection services)
{
//...
services.AddHostedService<SetupIdentityDataSeeder>();
}
This is not yet implemented. As a work around, just write your own class that will check the database for the existence of your entities, add them if they don't exist, and call this class from your Startup.cs.
My way:
Create Class in models folder
public static class ModelBuilderExtensions
{
public static void Seed(this ModelBuilder builder)
{
// Seed Roles
List<IdentityRole> roles = new List<IdentityRole>()
{
new IdentityRole { Name = "Admin", NormalizedName = "ADMIN" },
new IdentityRole { Name = "User", NormalizedName = "USER" }
};
builder.Entity<IdentityRole>().HasData(roles);
// -----------------------------------------------------------------------------
// Seed Users
var passwordHasher = new PasswordHasher<ApplicationUser>();
List<ApplicationUser> users = new List<ApplicationUser>()
{
// imporant: don't forget NormalizedUserName, NormalizedEmail
new ApplicationUser {
UserName = "user2#hotmail.com",
NormalizedUserName = "USER2#HOTMAIL.COM",
Email = "user2#hotmail.com",
NormalizedEmail = "USER2#HOTMAIL.COM",
},
new ApplicationUser {
UserName = "user3#hotmail.com",
NormalizedUserName = "USER3#HOTMAIL.COM",
Email = "user3#hotmail.com",
NormalizedEmail = "USER3#HOTMAIL.COM",
},
};
builder.Entity<ApplicationUser>().HasData(users);
///----------------------------------------------------
// Seed UserRoles
List<IdentityUserRole<string>> userRoles = new List<IdentityUserRole<string>>();
// Add Password For All Users
users[0].PasswordHash = passwordHasher.HashPassword(users[0], "User.123");
users[1].PasswordHash = passwordHasher.HashPassword(users[1], "User.155");
userRoles.Add(new IdentityUserRole<string> { UserId = users[0].Id, RoleId =
roles.First(q => q.Name == "User").Id });
userRoles.Add(new IdentityUserRole<string> { UserId = users[1].Id, RoleId =
roles.First(q => q.Name == "Admin").Id });
builder.Entity<IdentityUserRole<string>>().HasData(userRoles);
}}
in DBContext
public class AppDbContext : IdentityDbContext<ApplicationUser>
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
// Use seed method here
builder.Seed();
base.OnModelCreating(builder);
}}
Add the following class in Models namespace. It works for adding multiple users and roles, and will also add roles to existing users (e.g. facbook logins). Call it like this app.SeedUsersAndRoles(); from startup.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity;
namespace MyApplication.Models
{
public static class DataSeeder
{
public static async void SeedUsersAndRoles(this IApplicationBuilder app)
{
var context = app.ApplicationServices.GetService<ApplicationDbContext>();
UserWithRoles[] usersWithRoles = {
new UserWithRoles("Admin", new string[] { "Administrator" , "Distributor" },"somepassword"),//user and optional roles and password you want to seed
new UserWithRoles("PlainUser"),
new UserWithRoles("Jojo",new string[]{"Distributor" }) //seed roles to existing users (e.g. facebook login).
};
foreach (var userWithRoles in usersWithRoles)
{
foreach (string role in userWithRoles.Roles)
if (!context.Roles.Any(r => r.Name == role))
{
var roleStore = new RoleStore<IdentityRole>(context);
await roleStore.CreateAsync(new IdentityRole(role));
}
var ExistingUser = context.Users.FirstOrDefault(p => p.NormalizedUserName == userWithRoles.User.NormalizedUserName);
if (ExistingUser == null) //the following syntax: !context.Users.FirstOrDefault(p => p.NormalizedUserName == userWithRoles.User.NormalizedUserName))
//provokes execption:(ExecuteReader requires an open and available Connection.)
await new UserStore<ApplicationUser>(context).CreateAsync(userWithRoles.User);
await app.AssignRoles(userWithRoles); //assign also to existing users.
}
context.SaveChangesAsync();
}
public static async Task<IdentityResult> AssignRoles(this IApplicationBuilder app, UserWithRoles uWR)
{
UserManager<ApplicationUser> _userManager = app.ApplicationServices.GetService<UserManager<ApplicationUser>>();
ApplicationUser user = await _userManager.FindByNameAsync(uWR.User.NormalizedUserName);
var result = await _userManager.AddToRolesAsync(user, uWR.Roles);
return result;
}
}
public class UserWithRoles
{
private ApplicationUser user;
public ApplicationUser User { get { return user; } }
public string[] Roles { get; set; }
public UserWithRoles(string name, string[] roles = null, string password = "secret")
{
if (roles != null)
Roles = roles;
else
Roles = new string[] { };
user = new ApplicationUser
{
Email = name + "#gmail.com", NormalizedEmail = name.ToUpper() + "#GMAIL.COM",
UserName = name, NormalizedUserName = name.ToUpper(),
PhoneNumber = "+1312341234",
EmailConfirmed = true,
PhoneNumberConfirmed = true,
SecurityStamp = Guid.NewGuid().ToString("D"),
};
user.PasswordHash = new PasswordHasher<ApplicationUser>().HashPassword(user, password);
}
}
}
So this is solution based on Muhammad Abdullah answer. Included few code improvements, improved readability of code and got it to work with .net core 2.
public class Seed
{
public static async Task Initialize(IServiceProvider serviceProvider, IConfiguration configuration)
{
var usrName = configuration.GetSection("Admin").GetSection("UserName").Value;
var email = configuration.GetSection("Admin").GetSection("Email").Value;
var pass = configuration.GetSection("Admin").GetSection("Pass").Value;
var roles = new string[4] { OWNER, ADMIN, SENIOR, USER };
if(await CreateUser(serviceProvider, email, usrName, pass, roles))
{
await AddToRoles(serviceProvider, email, roles);
}
}
private static async Task<bool> CreateUser(IServiceProvider serviceProvider, string email, string usrName, string pass, string[] roles)
{
var res = false;
using (var scope = serviceProvider.CreateScope())
{
var context = scope.ServiceProvider.GetService<BaseContext>();
if (!context.ApplicationUsers.Any(u => u.NormalizedUserName == usrName.ToUpper()))
{
var roleStore = scope.ServiceProvider.GetService<RoleManager<IdentityRole>>();
foreach (string role in roles)
{
if (!context.Roles.Any(r => r.Name == role))
{
await roleStore.CreateAsync(new IdentityRole(role)).ConfigureAwait(false);
}
}
var user = new ApplicationUser
{
UserName = usrName,
Email = email,
EmailConfirmed = true,
NormalizedEmail = email.ToUpper(),
NormalizedUserName = usrName.ToUpper(),
PhoneNumber = null,
PhoneNumberConfirmed = true,
SecurityStamp = Guid.NewGuid().ToString()
};
var password = new PasswordHasher<ApplicationUser>();
user.PasswordHash = password.HashPassword(user, pass); ;
var userStore = new UserStore<ApplicationUser>(context);
res = (await userStore.CreateAsync(user).ConfigureAwait(false)).Succeeded;
}
return res;
}
}
private static async Task AddToRoles(IServiceProvider serviceProvider, string email, string[] roles)
{
using (var scope = serviceProvider.CreateScope())
{
var userManager = scope.ServiceProvider.GetService<UserManager<ApplicationUser>>();
var usr = await userManager.FindByEmailAsync(email).ConfigureAwait(false);
await userManager.AddToRolesAsync(usr, roles).ConfigureAwait(false);
}
}
}
Seems this thread is very old, but it will still work for someone who wants to seed their identity tables data in entityframework core.
You can simple try the below.
modelBuilder.Entity<IdentityUser>().HasData(
new IdentityUser { Id= "-1", UserName="sagark",PasswordHash="sagark", Email="emailid goes here" }
);
The following line create the entry in the AspNetRoles table but does not populate the NormalizedName column.
Substitute with the following for this column to be populated:
RoleManager<IdentityRole> roleManager = serviceProvider.GetService<RoleManager<IdentityRole>>();
roleManager.CreateAsync(new IdentityRole(role));

MVC Authorise not working from seeded user

I am having issues with getting the Authorise function to work on a controller. I have seeded a user as follows
protected override void Seed(WebApplication1.Models.ApplicationDbContext context)
{
var userStore = new UserStore<ApplicationUser>(context);
var userManager = new UserManager<ApplicationUser>(userStore);
if(!context.Users.Any(t => t.UserName == "markabarmi#hotmail.com"))
{
var user = new ApplicationUser { UserName = "markabarmi#hotmail.com", Email = "markabarmi#hotmail.com" };
userManager.Create(user, "passw0d!");
context.Roles.AddOrUpdate(r => r.Name, new IdentityRole { Name = "Admin" });
context.SaveChanges();
userManager.AddToRole(user.Id, "Admin");
}
}
From this I can log into the standard MVC5 application. But when I wish to put an Authorise onto a controller or ActionResult, the login will fail and I get Invalid login attempt. This is the home controller i'm adding Authorised onto.
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
//[Authorize(Roles = "Admin")]
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
}
If anyone could help me please :) Thanks
Not sure why you are not using a RoleManager since you have the UserManager part, but this is what works for me. AddToRole() will do it's own Saving so no need for context.SaveChanges():
var roleStore = new RoleStore<IdentityRole>(context);
var roleManager = new RoleManager<IdentityRole>(roleStore);
var userStore = new UserStore<ApplicationUser>(context);
var userManager = new UserManager<ApplicationUser>(userStore);
if (!context.Roles.Any())
{
// Add missing roles
var role = roleManager.FindByName("Admin");
if (role == null)
{
role = new IdentityRole("Admin");
roleManager.Create(role);
}
role = roleManager.FindByName("DataEntry");
if (role == null)
{
role = new IdentityRole("DataEntry");
roleManager.Create(role);
}
role = roleManager.FindByName("Limited");
if (role == null)
{
role = new IdentityRole("Limited");
roleManager.Create(role);
}
}
if (!context.Users.Any())
{
var user = userManager.FindByName("admin");
if (user == null)
{
var newUser = new ApplicationUser()
{
UserName = "admin",
FirstName = "Admin",
LastName = "User",
Email = "xxx#xxx.net",
PhoneNumber = "5556667777",
MustChangePassword = false
};
userManager.Create(newUser, "Password1");
userManager.SetLockoutEnabled(newUser.Id, false);
userManager.AddToRole(newUser.Id, "Admin");
}
}

Posting T with RestSharp to MVC4 api server gives null object

I have this common CUser class
public class CUser
{
public String Username { get; set; }
public String Password { get; set; }
}
Then I have this code on my client that uses RestSharp
public void CreateUser()
{
RestRequest request = new RestRequest(Method.POST);
request.RequestFormat = DataFormat.Json;
request.Resource = "user/{cUser}";
CUser user = new CUser
{
Username = "Foo",
Password = "BarBaz"
};
request.AddParameter("cUser", user, ParameterType.UrlSegment);
client.PostAsync<int>(request, (response, handler) =>
{
System.Diagnostics.Debug.WriteLine(response.StatusDescription);
System.Diagnostics.Debug.WriteLine("id: " + response.Data);
});
}
And this http route in my global.asax
routes.MapHttpRoute(
name: "CreateUser",
routeTemplate: "api/{controller}/{cUser}",
defaults: new
{
controller = "User",
action = "CreateUser",
cUser = RouteParameter.Optional
});
And this servercode to handle it
public int CreateUser(CUser cUser)
{
User user = new User(cUser);
LoginManager manager = new LoginManager();
return manager.CreateUser(user);
}
But everytime I run it cUser's values are null (Username and Password) so do I need to do something to restsharp to make it serialize it properly?
I think this is what you want:
request.AddParameter("username", user.Username);
request.AddParameter("password", user.Password);
What you're doing would result in cUser.ToString() being substituted for the {cUser} placeholder.

Resources