asp.net MVC3 Unit Testing - Role Provider - asp.net-mvc

Unit testing of the role provider to fail.
[TestMethod]
public void FindUsersInRole()
{
Mock<IUsersInRoleRepository> userInRoleMock = new Mock<IUsersInRoleRepository>();
userInRoleMock.Setup(m => m.UsersInRoles).Returns(new UsersInRole[] {
new UsersInRole { UserId = Guid.Parse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"), RoleId = Guid.Parse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa") },
new UsersInRole { UserId = Guid.Parse("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"), RoleId = Guid.Parse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa") },
new UsersInRole { UserId = Guid.Parse("cccccccc-cccc-cccc-cccc-cccccccccccc"), RoleId = Guid.Parse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa") },
new UsersInRole { UserId = Guid.Parse("dddddddd-dddd-dddd-dddd-dddddddddddd"), RoleId = Guid.Parse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa") },
new UsersInRole { UserId = Guid.Parse("eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee"), RoleId = Guid.Parse("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb") }
}.AsQueryable());
Mock<IRoleRepository> roleMock = new Mock<IRoleRepository>();
roleMock.Setup(m => m.Roles).Returns(new Role[] {
new Role { RoleId = Guid.Parse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"), RoleName = "test" },
new Role { RoleId = Guid.Parse("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"), RoleName = "admin" }
}.AsQueryable());
Mock<IUserRepository> userMock = new Mock<IUserRepository>();
userMock.Setup(m => m.Users).Returns(new User[] {
new User { UserId = Guid.Parse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"), UserAccount = "abcdef" },
new User { UserId = Guid.Parse("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"), UserAccount = "bcdef" },
new User { UserId = Guid.Parse("cccccccc-cccc-cccc-cccc-cccccccccccc"), UserAccount = "cdef" },
new User { UserId = Guid.Parse("dddddddd-dddd-dddd-dddd-dddddddddddd"), UserAccount = "bcdf" },
new User { UserId = Guid.Parse("eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee"), UserAccount = "abcde" }
}.AsQueryable());
RoleProvider target = new RoleProvider(userMock.Object, roleMock.Object, userInRoleMock.Object);
string[] result = target.FindUsersInRole("test", "cde");
Assert.AreEqual(result[0], "abcdef");
Assert.AreEqual(result[1], "bcdef");
Assert.AreEqual(result[2], "cdef");
}
Unit Test Code
string[] result = target.FindUsersInRole("test", "cde"); <-- error
FindUsersInRole - Gets an array of user names in a role where the user name contains the specified user name to match.
System.NullReferenceException is raised and try to debug.
Why NullReferenceException?
PS - FindUsersInRole (RoleProvider)
public override string[] FindUsersInRole(string roleName, string userAccountToMatch)
{
Guid roleId = roleRepository.GetRole(roleName).RoleId; // RoleId Retrun.. NullReferenceException
var roleInUsers = (from ru in usersInRoleRepository.UsersInRoles
where ru.RoleId == roleId
select ru.UserId).ToArray();
var findUserResult = (from u in userRepository.Users
where roleInUsers.Contains(u.UserId) && u.UserAccount.Contains(userAccountToMatch)
select u.UserAccount).ToArray();
return findUserResult;
}

Your cde is not a fake user in a mackUserAccount . So its return null.
try this below code string[] result = target.FindUsersInRole("test", "abcdef"); instead of
string[] result = target.FindUsersInRole("test", "cde");

Related

add role in database in asp mvc identity

i need to when user regiter add in tabel AspNetRole add user id and role id .
but when i create a user show me this error .
how can i insert role in database ?
/*************************************************************************************************/
identityconfig :
public class ApplicationRoleManager : RoleManager<IdentityRole>
{
public ApplicationRoleManager(IRoleStore<IdentityRole, string> roleStore)
: base(roleStore)
{
}
public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context)
{
return new ApplicationRoleManager(new RoleStore<IdentityRole>(context.Get<ApplicationDbContext>()));
}
}
public static class SecurityRole
{
public const string Admin = "admin";
public const string Accounting = "accounting";
}
StartupAuth :
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
AccountController :
public ApplicationRoleManager RoleManager
{
get
{
return _roleManager ?? HttpContext.GetOwinContext().Get<ApplicationRoleManager>();
}
private set
{
_roleManager = value;
}
}
public async Task<ActionResult> Register(RegisterViewModel model, HttpPostedFileBase IamgeProfile)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Username, Email = model.Email };
user.Name = model.Name;
user.Family = model.Family;
user.Address = model.Address;
user.BankName = model.BankName;
user.City = model.City;
user.Ostan = model.Ostan;
user.PhoneNumber = model.PhoneNumber;
user.HomeNumber = model.HomeNumber;
user.ShabaNo = model.ShabaNo;
user.PostaCode = model.PostaCode;
user.NationalCode = model.NationalCode;
if (IamgeProfile != null)
{
IamgeProfile = Request.Files[0];
var ext = System.IO.Path.GetExtension(IamgeProfile.FileName);
if (ext == ".jpeg" || ext == ".jpg" || ext == ".png")
{
string filename = model.Name + model.Family + model.NationalCode + ext;
IamgeProfile.SaveAs(Server.MapPath(#"~/Images/UserImageProfile/" + filename));
user.IamgeProfile = filename;
}
}
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
await UserManager.AddToRoleAsync(user.Id, role: SecurityRole.Accounting);
var code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking this link: link");
ViewBag.Link = callbackUrl;
return View("DisplayEmail");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
To add a role into AspNetRoles you can do this in your Seed() or other startup method:
if (!context.Roles.Any(r => r.Name == "Admin"))
{
var store = new RoleStore<IdentityRole>(context);
var manager = new RoleManager<IdentityRole>(store);
var role = new IdentityRole { Name = "Admin" };
manager.Create(role);
}
https://msdn.microsoft.com/en-us/library/dn613057(v=vs.108).aspx

Seed Custom Role Inherited from IdentityRole

this time the problem is when I try to build a class to inherit from IdentityRole like this
public class Role : IdentityRole, IObjectState
{
public Role() { }
public Role(string name) : base(name) { Name = name; }
public new string Name { get; set; }
[NotMapped]
public ObjectState ObjectState { get; set; }
public virtual List<UserPermission> UserPermissions { get; set; }
}
then I want to Seed my Database with my Roles, but its Discriminator Column I want it with the value 'Role' not 'IdentityRole'
this my seeding code
if (!context.Roles.Any(r => r.Name == "Administrator") || !context.Roles.Any(r => r.Name == "User"))
{
var store = new RoleStore<IdentityRole>(context);
var manager = new RoleManager<IdentityRole>(store);
var role = new List<IdentityRole>()
{
new IdentityRole { Name = "Administrator"},
new IdentityRole { Name = "User"},
};
role.ForEach(x => manager.Create(x));
}
when I try this seeding code It's Ok, in its Discriminator Column It says 'IdentityRole' but when I try this one, It doesn't save the Role in the table
if (!context.Roles.Any(r => r.Name == "qwe") || !context.Roles.Any(r => r.Name == "qweqwe"))
{
var store = new RoleStore<Role>(context);
var manager = new RoleManager<Role>(store);
List<Role> role = new List<Role>()
{
new Role() { Name = "qwe"},
new Role() { Name = "qweqwe"},
};
role.ForEach(x => manager.Create(x));
}
I don't know why this code can't save the role, as you can see I should save it because the Role Class has inherited from IdentityRole
What should I do to seed my Roles with different Discriminator?
Thanks in advanced
Ok, my solution is very simple lol
I changed this
if (!context.Roles.Any(r => r.Name == "qwe") || !context.Roles.Any(r => r.Name == "qweqwe"))
{
var store = new RoleStore<Role>(context);
var manager = new RoleManager<Role>(store);
List<Role> role = new List<Role>()
{
new Role() { Name = "qwe"},
new Role() { Name = "qweqwe"},
};
role.ForEach(x => manager.Create(x));
}
for this
if (!context.Roles.Any(r => r.Name == "Administrator") || !context.Roles.Any(r => r.Name == "User"))
{
var role = new List<Role>()
{
new Role { Name = "Administrator"},
new Role { Name = "User"},
};
role.ForEach(x => context.Roles.Add(x));
}
That's it
I realized that you can seed your table using your context, without instance your ApplicationRole or UserManager

MVC 5.1 identity 2 add new Role to myself need to log out

When I add new Role to my own account I have to log out and log back in so this role will start working. Is there a way to re-load roles on the fly (after adding/deleting) ?
I'm using Individual Accounts stored in Ms SQL Server 2012 in MVC 5.1.2 and Identity v. 2.0.0
Below is controller code:
// GET: /Users/Edit/1
public async Task<ActionResult> Edit(string id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var user = await UserManager.FindByIdAsync(id);
if (user == null)
{
return HttpNotFound();
}
var userRoles = await UserManager.GetRolesAsync(user.Id);
return View(new EditUserViewModel()
{
Id = user.Id,
Email = user.Email,
FirstName = user.FirstName,
LastName = user.LastName,
CustomerID = user.CustomerID,
siteID = user.SiteID,
RolesList = RoleManager.Roles.ToList().Select(x => new SelectListItem()
{
Selected = userRoles.Contains(x.Name),
Text = x.Name,
Value = x.Name
}),
SitesList = db.sites.ToList().Select(y=> new SelectListItem()
{
Selected= user.SiteID==y.siteID,
Text = y.siteCode,
Value= y.siteID.ToString()
})
});
}
//
// POST: /Users/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit([Bind(Include = "Email,Id,FirstName,LastName,CustomerID,siteID")] EditUserViewModel editUser, params string[] selectedRole)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindByIdAsync(editUser.Id);
if (user == null)
{
return HttpNotFound();
}
user.UserName = editUser.Email;
user.Email = editUser.Email;
user.FirstName = editUser.FirstName;
user.LastName = editUser.LastName;
user.CustomerID = editUser.CustomerID;
user.SiteID = editUser.siteID;
var userRoles = await UserManager.GetRolesAsync(user.Id);
selectedRole = selectedRole ?? new string[] { };
var result = await UserManager.AddUserToRolesAsync(user.Id, selectedRole.Except(userRoles).ToList<string>());
if (!result.Succeeded)
{
ModelState.AddModelError("", result.Errors.First());
return View();
}
result = await UserManager.RemoveUserFromRolesAsync(user.Id, userRoles.Except(selectedRole).ToList<string>());
if (!result.Succeeded)
{
ModelState.AddModelError("", result.Errors.First());
return View();
}
return RedirectToAction("Index");
}
editUser.RolesList = RoleManager.Roles.ToList().Select(x => new SelectListItem()
{
//Selected = userRoles.Contains(x.Name),
Text = x.Name,
Value = x.Name
});
ModelState.AddModelError("", "Something failed.");
return View(editUser);
}

Why is UserManager.Find() returning null if my UserName is email based?

I'm trying to implement email address based usernames in AspNet.Identity for MVC5, but I'm having trouble with the UserManager finding my user.
public UserManager<ApplicationUser> UserManager { get; private set; }
public AccountController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
UserManager.UserValidator = new UserValidator<ApplicationUser>(UserManager)
{
AllowOnlyAlphanumericUserNames = false
};
}
In my login post method:
var user = await UserManager.FindAsync(model.UserName, model.Password);
user is null.
Am I using the wrong method to find my user by username and password?
Even if I use
var db = new ApplicationDBContext();
var user = db.Users.Find(model.UserName);
or
var db = new ApplicationDBContext();
var user = db.Users.FirstOrDefault(u => u.UserName == model.UserName);
I get a null
UPDATE
It looks like I'm getting null, because the users I'm trying to seed aren't being seeded. Anyone know why?
This is my seed for the users in the Configuration.cs (migrations):
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
var users = new List<ApplicationUser>()
{
new ApplicationUser { UserName = "batman#email.com", IsActive = true },
new ApplicationUser { UserName = "superman#email.com", IsActive = true },
new ApplicationUser { UserName = "wonderwoman#email.com", IsActive = false }
};
users.ForEach(i => manager.Create(i, "password"));
If I seed the users with non-email UserNames, the seed goes through with no problem:
new ApplicationUser { UserName = "batman", IsActive = true },
new ApplicationUser { UserName = "superman", IsActive = true },
new ApplicationUser { UserName = "wonderwoman", IsActive = false }
Got it. I needed to change the validator in my seed:
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = false
};
var users = new List<ApplicationUser>()
{
new ApplicationUser { UserName = "batman#email.com", IsActive = true },
new ApplicationUser { UserName = "superman#email.com", IsActive = true },
new ApplicationUser { UserName = "wonderwoman#email.com", IsActive = false }
};
users.ForEach(i => manager.Create(i, "December 2013"));
After this, I was able to seed my email-based UserNames.
I left this in my AccountController for adding users:
public AccountController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
UserManager.UserValidator = new UserValidator<ApplicationUser>(UserManager)
{
AllowOnlyAlphanumericUserNames = false
};
}
Verify you have added Database Init Strategy Or doing manual updates.
e.g. [Database Init Strategy]
Database.SetInitializer<ApplicationDbContext>(new System.Data.Entity.MigrateDatabaseToLatestVersion<ApplicationDbContext, Configuration>());

How to create foreign key relationship in Entity Framework CodeFirst

I'm new to Entity Framework, which I'm using for an ASP.NET MVC4 project. I'm trying to create a foreign key relationship and am not having much success. The problem may be in my seed data, which I'm not sure how to restructure from an earlier attempt to get this working.
Here are my two classes:
public class HardwareType
{
public int Id { get; set; }
[Required]
[StringLength(128)]
public string HType { get; set; }
public int HardwareId { get; set; }
public virtual Hardware Hardware { get; set; }
}
and
public class Hardware
{
public int Id { get; set; }
//public int HardwareId { get; set; }
...
public virtual ICollection<HardwareType> HardwareType { get; set; }
}
Here is my sample seed data:
protected override void Seed(Context context)
{
var loc = new List<Location> {
new Location { LocationName = "Paradise Lane" },
new Location { LocationName = "81st Street" }
};
loc.ForEach(l => context.Locations.Add(l));
var type = new List<SoftwareType> {
new SoftwareType { SType = "Suite" }
};
type.ForEach(t => context.SoftwareTypes.Add(t));
var pub = new List<SoftwarePublisher> {
new SoftwarePublisher { Publisher = "Adobe" },
new SoftwarePublisher { Publisher = "Apple" },
new SoftwarePublisher { Publisher = "Microsoft" }
};
var soft = new List<Software> {
new Software { Title = "Adobe Creative Suite", Version = "CS6", SerialNumber = "1234634543", Platform = "Mac", Notes = "Macs rock!", PurchaseDate = "2012-12-04", Suite = true, SubscriptionEndDate = null, SeatCount = 0, Locations = loc.Where(s => s.LocationName == "Paradise Lane").ToArray(), Types = type.Where(s => s.SType == "Suite").ToArray(), Publishers = pub.Where(s => s.Publisher == "Adobe").ToArray() },
new Software { Title = "Microsoft Office", Version = "2012", SerialNumber = "34252345", Platform = "PC", Notes = "PCs stink!", PurchaseDate = "2012-11-04", Suite = true, SubscriptionEndDate = null, SeatCount = 0, Locations = loc.Where(s => s.LocationName == "81st Street").ToArray(), Types = type.Where(s => s.SType == "Suite").ToArray(), Publishers = pub.Where(s => s.Publisher == "Microsoft").ToArray() },
new Software { Title = "Apple iLife", Version = "2012", SerialNumber = "54675747564", Platform = "Mac", Notes = "Macs still rock!", PurchaseDate = "2012-12-04", Suite = true, SubscriptionEndDate = null, SeatCount = 0, Locations = loc.Where(s => s.LocationName == "Paradise Lane").ToArray(), Types = type.Where(s => s.SType == "Suite").ToArray(), Publishers = pub.Where(s => s.Publisher == "Apple").ToArray() }
};
soft.ForEach(s => context.Software.Add(s));
var manuf = new List<Manufacturer> {
new Manufacturer { ManufacturerName = "SonicWall" },
new Manufacturer { ManufacturerName = "Cisco" },
new Manufacturer { ManufacturerName = "Barracuda" },
new Manufacturer { ManufacturerName = "Dell" },
new Manufacturer { ManufacturerName = "HP" },
new Manufacturer { ManufacturerName = "Maxtor" },
new Manufacturer { ManufacturerName = "LaCie" },
new Manufacturer { ManufacturerName = "APC" },
new Manufacturer { ManufacturerName = "Intel" },
new Manufacturer { ManufacturerName = "D-Link" },
new Manufacturer { ManufacturerName = "Western Digital" },
new Manufacturer { ManufacturerName = "Quantum" },
new Manufacturer { ManufacturerName = "Seagate" },
new Manufacturer { ManufacturerName = "Apple" },
new Manufacturer { ManufacturerName = "Canon" },
};
var device = new List<DeviceType> {
new DeviceType { DType = "Network Device"},
new DeviceType { DType = "Other"}
};
var htype = new List<HardwareType> {
new HardwareType { HType = "PC" },
new HardwareType { HType = "Monitor" },
new HardwareType { HType = "Printer" },
new HardwareType { HType = "Miscellaneous" }
};
var hard = new List<Hardware> {
new Hardware { AssetTagId = "2134", Type = device.Where(h => h.DType == "Network Device").ToArray(), Manufacturer = manuf.Where(h => h.ManufacturerName == "SonicWall").ToArray(), ServiceTagId = "5243", SerialNumber = "3456", ProductNumber = "2345", PurchaseDate = "2012-10-23", WarrantyExpiration = "2012-11-12", WarrantyType = "NBD", Location = loc.Where(h => h.LocationName == "Paradise Lane").ToArray(), Notes = "Scrapped", HardwareType = htype.Where(h => h.HType == "Monitor").ToArray()},
new Hardware { AssetTagId = "2134", Type = device.Where(h => h.DType == "Network Device").ToArray(), Manufacturer = manuf.Where(h => h.ManufacturerName == "SonicWall").ToArray(), ServiceTagId = "5243", SerialNumber = "3456", ProductNumber = "2345", PurchaseDate = "2012-10-23", WarrantyExpiration = "2012-11-12", WarrantyType = "NBD", Location = loc.Where(h => h.LocationName == "Paradise Lane").ToArray(), Notes = "Scrapped", HardwareType = htype.Where(h => h.HType == "PC").ToArray() },
new Hardware { AssetTagId = "2134", Type = device.Where(h => h.DType == "Network Device").ToArray(), Manufacturer = manuf.Where(h => h.ManufacturerName == "SonicWall").ToArray(), ServiceTagId = "5243", SerialNumber = "3456", ProductNumber = "2345", PurchaseDate = "2012-10-23", WarrantyExpiration = "2012-11-12", WarrantyType = "NBD", Location = loc.Where(h => h.LocationName == "Paradise Lane").ToArray(), Notes = "Scrapped", HardwareType = htype.Where(h => h.HType == "PC").ToArray() }
};
hard.ForEach(h => context.Hardwares.Add(h));
base.Seed(context);
}
How do I structure this so the foreign key relationship works. Right now, I get this error: Unable to set field/property HardwareType on entity type CIT.Models.Hardware. See InnerException for details.
The inner exception is: An item cannot be removed from a fixed size Array of type 'CIT.Models.HardwareType[]'.
try changing you'r tables structure like this :
public class Hardware
{
public int Id { get; set; }
.
.
.
public HardwareTypeId { get; set; }
public virtual HardwareType hardwareType {get;set;}
}
and HardwareType :
public class HardwareType
{
public int Id { get; set; }
public string TypeName {get;set;}
}

Resources