How to check If entry exist in Table? MVC - asp.net-mvc

I am designing something similar to facebook groups. I have user table and Community with one relationship table name CommunityUser. I want to know if the user already joined a community or not? This can take if the communityID exist against that userID in CommunityUser Table.
Here is my IsMember() function code.
public bool IsMember(string UserID, int CommunityID)
{
var MembershipUser = db.Users.Include(x => x.CommunityUsers).Where(s => s.Id == UserID).FirstOrDefault();
var Membership = MembershipUser.CommunityUsers.Count();
if (Membership > 0)
return true;
else
return false;
}
I have virtual connection in my User Table
public virtual ICollection<CommunityUser> CommunityUsers { get; set; }
public ApplicationUser()
{
CommunityUsers = new Collection<CommunityUser>();
}

If you are planning on returning a boolean value, just consider using the Any() method:
public bool IsMember(string UserID, int CommunityID)
{
// This will return if a given user exists
return db.Users.Any(u => u.Id == UserId);
}
Likewise, you could also consider pulling in the related CommunityUsers collection and checking that within your query as well:
public bool IsMember(string UserID, int CommunityID)
{
// This will return true if a given user exists and if a specific
// CommunityId is present for that user
return db.Users.Include("CommunityUsers")
.Any(u => u.Id == UserId && u.CommunityUsers.Any(c => c.Id == CommunityId));
}

Related

What's the return value of DBSet.Add(object o)

Consider the situation.
I have a userlogin table. the userlogin has the following fields.
userid(identity(1,1)), username(unique), password(string)
I have another table, userRole with following fields.
userid(fk referencing userlogin), role(string)
Now suppose I want to add an admin user to my empty application database.
What I am currently doing is:
// Check Userlogin if it contains adminuser1 as username, if not, add adminuser1 with password xyz.
UserLogin login = new UserLogin();
login.username = "adminuser1";
login.password = "xyz";
context.UserLogins.Add(login);
context.SaveChanges();
// query again from database to get the userid
Userlogin user = context.UserLogins.Single(l => (l.username == "adminuser1") && (l.password == "xyz"));
int userid = user.userid;
UserRole admin = new UserRole();
admin.userid = userid;
admin.role = "admin";
context.UserRoles.Add(admin);
context.SaveChanges();
I want to make it a less troublesome, if we can get the userid of userRecently Added, without making another request.
I mean I want to do this if it is possible.
UserLogin login = new UserLogin();
login.username = "adminuser1";
login.password = "xyz";
UserLogin user = context.UserLogins.Add(login);
UserRole admin = new UserRole();
admin.userid = user.userid;
admin.role = "admin";
context.UserRoles.Add(admin);
context.SaveChanges();
Update
I also wanted to know if there is some way to do
context.UserLogins.Single(l => l == login);
instead of
context.UserLogins.Single(l => (l.username == "adminuser1") && (l.password=="xyz"));
because I use the same method in large classes in many fields.
It can be different based on your needs but you can have something like:
public class UserRole
{
public int Id { get; set; }
public string role { get; set; }
}
public class UserLogin
{
public int Id { get; set; }
public string username { get; set; }
public string password { get; set; }
public UserRole Role { get; set; }
}
and then use them like:
var login = new UserLogin
{
username = "adminuser1",
password = "xyz"
};
var admin = context.UserRoles.Single(_=> _.role == "admin");
if (admin == null)
{
admin = new UserRole
{
role = "admin"
};
}
login.Role = admin;
context.UserLogins.Add(login);
context.SaveChanges();
Your models' relationship seems wrong but based on your information you can have this:
var login = context.UserLogins.Single(_ => _.username == "adminuser1");
if (login == null)
{
login = new UserLogin();
login.username = "adminuser1";
login.password = "xyz";
context.UserLogins.Add(login);
context.SaveChanges();
}
else
{
// this user already exists.
}
var admin = context.UserRoles.Single(_ => _.role == "admin");
if (admin == null)
{
admin.userid = login.userid;
admin.role = "admin";
context.UserRoles.Add(admin);
context.SaveChanges();
}
else
{
// the role already exists.
}
context.UserLogins.Single(l => l == login); would not work for you! you have to query DB based on your model key, not whole model data!
For the question
What's the return value of DBSet.Add(object o)
The answer is: it will return the same object o(i.e. without the userid). Simply because userid is an identity column and relies on the database, its value is only available after context.SaveChanges() is called. Since Add() method only registers that a change will take place after SaveChanges() is called.
For the answer to update,
Instead of using
context.UserLogins.Single(l => (l.username == "adminuser1") && (l.password=="xyz"));
For classes that have many fields, I can check if there are any unique columns. For example. I could use, simply
context.UserLogins.Single(l => l.username == "adminuser1");
Just because, username(unique) is specified in the question.
I would rather recommend people use a single Stored Procedure. The calling of context.SaveChanges() and the context.xyz.Single() require opening database connection multiple times. For optimising performance you can use Stored Procedures, as they require only one connection per task. For more information.
Understang Performance Considerations
As I am using database first approach, I found this link also helpful.
Use Stored Procedure in Entity Framework
Thanks :)

Deny user with manager role to edit users with admin role Asp.Net MVC5 Identity

I have set the app to allow each user to have multiple roles.
public class SelectRoleViewModel
{
public string Id { get; set; }
public bool Checked { get; set; }
public string RoleName { get; set; }
public string Description { get; set; }
}
public class EditUser
{
// other properties
public List<SelectRoleViewModel> Roles { get; set; }
}
now in the Controlles, in the Edit get method I wrote this
[CustomAuthorize(Roles = ("Admin,Manager"))]
public ActionResult Edit(string Id)
{
var editUser = GetEditUser(Id);
bool isAdmin = User.IsInRole("Admin");
if (!isAdmin)
{
if (editUser.Roles.Exists(x => x.RoleName == "Admin"))
{
return RedirectToAction("AccessNotAllowed", "Errors");
}
}
// Here just edit what you want
return View(editUser);
}
private EditUser GetEditUser(string Id)
{
var dbUser = UserManager.Users.Where(x => x.Id == Id).FirstOrDefault();
var currentRoles = dbUser.Roles.Select(x => x.RoleId).ToList();
var allRoles = _roleManager.Roles.ToList();
EditUser editUser = new EditUser();
foreach (var x in allRoles)
{
if (currentRoles.Contains(x.Id))
editUser.Roles.Add(new SelectRoleViewModel { Id = x.Id, RoleName = x.Name, Description = x.Description, Checked = true });
else
editUser.Roles.Add(new SelectRoleViewModel { Id = x.Id, RoleName = x.Name, Description = x.Description, Checked = false });
}
if (User.IsInRole("Manager"))
{
// don't show the admin role to set for users if authenticated user is manager
var adm = editUser.Roles
.Where(x => x.RoleName.Equals("Admin", StringComparison.OrdinalIgnoreCase))
.FirstOrDefault();
if (adm != null)
{
editUser.Roles.Remove(adm);
}
}
editUser.FirstName = dbUser.FirstName;
editUser.LastName = dbUser.LastName;
editUser.Email = dbUser.Email;
editUser.UserName = dbUser.UserName;
editUser.Id = dbUser.Id;
return editUser;
}
So, the manager has the right to edit users and to create them, but manager can't create users with admin role.
What I'm trying to do is to deny access for the manager to edit the admin users.
The code I wrote, it takes the whole list of user roles, and since there is an admin role, it always denies access to edit users.
This happens when I comment out this code in the GetEditUser method:
if (User.IsInRole("Manager"))
{
// don't show the admin role to set for users if authenticated user is manager
var adm = editUser.Roles
.Where(x => x.RoleName.Equals("Admin", StringComparison.OrdinalIgnoreCase))
.FirstOrDefault();
if (adm != null)
{
editUser.Roles.Remove(adm);
}
}
and with this code (uncommented), it totally removes the admin role from the list, so the manager can still edit the admin users since it don't find the admin role to compare in the if condition.
Can someone help me find a solution to limit manager access for editing admin users and to hide the admin role for managers when creating new user, without changing the users to assign only 1 role? The logic of the app needs to have multiple roles per user.
Move the indicated section of code to the Edit method inside the if(!isAdmin):
if (!isAdmin)
{
if (editUser.Roles.Exists(x => x.RoleName == "Admin" && x.Checked))
{
return RedirectToAction("AccessNotAllowed", "Errors");
}
var adm = editUser.Roles
.Where(x => x.RoleName.Equals("Admin", StringComparison.OrdinalIgnoreCase))
.FirstOrDefault();
if (adm != null)
{
editUser.Roles.Remove(adm);
}
}

How to find all ApplicationRoles of a user in asp.net identity 2.0

I tried following code to get all the roles object (i.e. ApplicationRole not the IdentityUserRole) of a user.
string userId = User.Identity.GetUserId();
var RoleManager = this.HttpContext.GetOwinContext().Get<ApplicationRoleManager>();
var UserManager = this.HttpContext.GetOwinContext().Get<ApplicationUserManager>();
// var u = RoleManager.FindByName("").Users;
// var r = UserManager.FindById(userId).Roles;
var roleNames = ((ClaimsIdentity)User.Identity).Claims
.Where(c => c.Type == ClaimTypes.Role)
.Select(c => c.Value);
var userRoles = (from roles in RoleManager.Roles
where roleNames.Contains(roles.Name)
select roles
).ToList();
But it not seem consistent and trivial and it works Only with the current user. I hope there would be some better way of doing this.
Edit 1:
My RoleManager is the class derived from IdentityRole have some extra properties e.g. Description.
public class ApplicationRole : IdentityRole
{
public ApplicationRole() : base() { }
public ApplicationRole(string name, string description)
: base(name)
{
this.Description = description;
}
public virtual string Description { get; set; }
}
Note: IdentityUserRole / user.Roles / role.Users are not the Roles. All three represent the joining table between User & Role
var selectedRoleNames = from uf in user.UserRoles
join r in RoleManager.Roles on uf.RoleID equals r.ID
select r;
This gets roles for the given user. If the given user is not the current user, then don't use User.Identity, but get the user via UserManager.
Or, if you already have any user id then...
var selectedRoleNames = from r in RoleManager.Roles
where r.Users.Select(u => u.UserId).Contains(user.Id)
select r;

Remove User from Roles in ASP.NET Identity 2.x

How can I remove User from Roles in ASP.NET Identity 2.x ?
about adding role to user there is no problem but when I want to remove a role from a user I cannot.It should be mentioned that there is no exception or error!
//POST: Admin/User/Edit/5
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit([Bind(Prefix = "")]UserViewModel userViewModel, List<int> availableRoles)
{
if (ModelState.IsValid)
{
List<int> newListOfRolesIDs = availableRoles;
List<int> oldListOfRolesIDs = UserBLL.Instance.GetRolesIDs(userViewModel.Id);
List<int> deletedList;
List<int> addedList;
var haschanged = oldListOfRolesIDs.ChangeTracking(newListOfRolesIDs, out deletedList, out addedList);
using (new EFUnitOfWorkFactory().Create())
{
if (haschanged)
{
UserBLL.Instance.InsertRoles(addedList, userViewModel.Id);
UserBLL.Instance.DeleteRoles(deletedList, userViewModel.Id);
}
await UserBLL.Instance.UpdateAsync(userViewModel);
}
//ArticleBLL.Instance.UpdatePartial(articleViewModel, m => m.Title);
return RedirectToAction("Edit");
}
return View(userViewModel);
}
Delete Role method:
public void DeleteRoles(List<int> deleteList, int? userId)
{
if (userId != null)
{
User user = UserManager.FindByIdAsync(userId.Value).Result;
foreach (var i in deleteList)
{
user.Roles.Remove(new UserRole { RoleId = i, UserId = user.Id }); // What's the problem?!
}
}
}
Insert Role method:
public void InsertRoles(List<int> insertList, int? userId)
{
if (userId != null)
{
User user = UserManager.FindByIdAsync(userId.Value).Result;
foreach (var i in insertList)
{
user.Roles.Add(new UserRole { RoleId = i, UserId = user.Id });
}
}
}
What you are looking for is the RemoveFromRoleAsync method. An example would look similar to the following:
public async Task DeleteRolesAsync(List<string> deleteList, int? userId)
{
if (userId != null)
{
foreach (var roleName in deleteList)
{
IdentityResult deletionResult = await UserManager.RemoveFromRoleAsync(userId, roleName);
}
}
}
If you already have the ID of the user, there's no need to get the user again (only if you want to make sure that the user really exists; then you have to wrap your foreach with an if-statement). The deletion methods needs the name of the role, instead of the ID, to delete the user from the role. You can use the result of the operation (in my example stored in deletionResult) to make sure that the operation was successful. Remember that the name of the user manager (in my example UserManager) can vary depending on your implementation.
I had the same issue and what I ended up using was the
RemoveFromRolesAsync(string userId, params string[] roles) Method
from the UserManager.
Using the role names in an array works.
But has an issue that is if the user is not in one of the roles in the array the user will not be removed from any roles in the array.
All or nothing.
var usr = UserManager.FindById(usrV.ID.ToString());
string[] deleteList;
deleteList= new string[1];
deleteList[0] = "Engineer";
var rresult1 = UserManager.RemoveFromRolesAsync(usr.Id, deleteList);
Hope it helps
You might want to check out this blog post. The ASP.NET team has a sample that includes adding and removing roles from a user.
ASP.NET Identity 2.0: Customizing Users and Roles

Getting userId of logged in user returns null

I am designing an ASP.net MVC4 application and I need to get the current user ID so that I'll save it in a table in my database as an owner id for a group.
This is the code I am using:
public ActionResult CreateGroup(string groupName, string description)
{
if (Request.IsAuthenticated)
{
Group group = new Group();
Random random = new Random();
int groupId = random.Next(1, 2147483647);
using (CodeShareEntities conn = new CodeShareEntities())
{
try
{
int ownerId = (int) Membership.GetUser(System.Web.HttpContext.Current.User.Identity.Name).ProviderUserKey;
group.GroupId = groupId;
group.GroupName = groupName;
group.Description = description;
group.OwnerId = ownerId;
conn.Group.Add(group);
conn.SaveChanges();
}
catch (Exception e)
{
ModelState.AddModelError("", e.Message);
}
}
return View("ThisGroup");
}
else
{
return View("../Shared/NotLoggedIn");
}
I am getting a NullReferenceException on this line:
int ownerId = (int) Membership.GetUser(System.Web.HttpContext.Current.User.Identity.Name).ProviderUserKey;
although the username is returning correctly. What can be the problem? I am still new to web applications and I really can't figure this out!
Thanks
Unless you are using a custom membership provider, I believe that the ProvidersUserKey is a Guid.
(Guid) Membership.GetUser(System.Web.HttpContext.Current.User.Identity.Name).ProviderUserKey;
Try this code.it is work if you use aspnet membership provider.
MembershipUser user = Membership.GetUser(HttpContext.User.Identity.Name);
Guid guid = (Guid)user.ProviderUserKey;
Here is the helper method to retrieves current Logged-in user's ID.
Please note that ASP.Net Membership use Guid as ID (rather than integer).
public static Guid? UserId
{
get
{
try
{
Guid? userId = null;
if (HttpContext.Current != null &&
HttpContext.Current.User.Identity.IsAuthenticated)
{
MembershipUser currentUser = Membership.GetUser();
userId = (Guid)currentUser.ProviderUserKey;
}
return userId;
}
catch
{
return null;
}
}
}
Note: you want to check the returned UserId is not null and group.OwnerId is Guid too; otherwise, your save statement will fail.

Resources