SimpleMembership MVC 4 get data from UserProfile having role in webpages_Roles - asp.net-mvc

I have the following code. But there must be a more database efficient way to do this, because, correct me if Im wrong the number of database queries is
(1 + (qty of users with admin role))
With a new MVC 4 project the membership defaults are the tables UserProfile, webpages_Roles and webpages_UsersInRoles. I see lots of built in methods for Roles.Get*. If I want to avoid writing code like what I have below do I need to explicitly create a model for webpages_Roles and webpages_UsersInRoles as well as all the code first properties? Getting just the username from Roles.Get* doesnt suffice, I need the full UserProfile.
FYI the "UserRole" object below is just an enum
public ActionResult Admins()
{
var dbContext = new UsersContext();
var usernames = Roles.GetUsersInRole(UserRole.SiteAdministrator.ToString());
var adminUsers = new List<UserProfile>();
foreach (string username in usernames)
{
var adminUser = dbContext.UserProfiles.FirstOrDefault(u => u.UserName.ToLower() == username);
adminUser.Roles.Add(UserRole.SiteAdministrator);
adminUsers.Add(adminUser);
}
return View(adminUsers);
}

Yes, you don't want to do it that way. That's a very inefficient way.
Instead, use the tools as they were designed. For example, something like this:
var usernames = Roles.GetUsersInRole(UserRole.SiteAdministrator.ToString());
var adminUsers = dbContext.UserProfiles
.Where(x => usernames.Contains(x.Username)).ToList();
return View(adminUsers);

Related

ASP.NET MVC 5 API, Changing a class in GET function

I'm working on a dotnet mvc5 application. Here's a function from my api of customer controller
public IHttpActionResult GetCustomers()
{
var customerDtos = _context.Customers.ToList().Select(Mapper.Map<Customer, CustomerDto>);
return Ok(customerDtos);
}
I need to add "TYPEAHEAD" plugin to my application. The video series/instructor I'm following says to make the function code change to
public IHttpActionResult GetCustomers(string query = null)
{
var customersQuery = _context.Customers
.Include(c => c.MembershipType);
if (!String.IsNullOrWhiteSpace(query))
customersQuery = customersQuery.Where(c => c.Name.Contains(query));
var customerDtos = customersQuery
.ToList()
.Select(Mapper.Map<Customer, CustomerDto>);
return Ok(customerDtos);
}
in order to make "TypeAhead" plug in work on my view.
The only problem is previously while creating customers I didn't feel the need to add "MembershipType" class to my customer. So how do I use the new code without MembershipType. Is there any other attribute I can replace it with? Name, ID etc.
.Include(c => c.MembershipType);
essentially means that you also want to include the 'child' collection of MembershipType
See here for more information on Loading Related Entities
For your case, you can simply omit this.
public IHttpActionResult GetCustomers(string query = null)
{
var customersQuery = _context.Customers;
if (!String.IsNullOrWhiteSpace(query))
customersQuery = customersQuery.Where(c => c.Name.Contains(query));
var customerDtos = customersQuery
.ToList()
.Select(Mapper.Map<Customer, CustomerDto>);
return Ok(customerDtos);
}
You don't need to replace it with anything.
customersQuery is then an IQueryable<Customer> which the rest of this code can append Where clause to.
It is not executed against the database until the ToList call.

Save model in session and use it in view

I've been looking at some of the answers on this site about saving model data to session but none seem to work for me, or most likely I am not understanding it correctly and not sure how to implement it.
This is the latest solution I've been trying.
c# - How to save object to session in ASP.NET
In the Index I get an error on declaring the model telling me User doesn't exist
Model
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
Controller
public ActionResult Index()
{
using (DefaultConnection db = new DefaultConnection())
{
var model = from u in db.Users select u;
var vm = (User)Session["User"];
return View(vm);
}
}
View
#model User
#Model.Username
I am not quite sure what you are trying to achieve here. But i can see some problems in your code
var vm = (User)Session["User"];
You are trying to access a session variable with key User and trying to cast it to a User instance. That means, Before executing this code, you should be setting a valid user object to Session["User"]. If you do not do that, your casting will fail(code will crash) because Session does not have any item for the key "User"
If you haven't set it yet, Before accessing this session object, you should set a valid User object to session.
var us = new User { Id=1, Username="test"};
Session["User"] = us;
Later, before accessing from session item, you should always check whether it is null or not
User u = null;
if(Session["User"]!=null)
{
u = Session["User"] as User;
// you may use u now.
}
Also, you are querying from the Users table and selecting the records to the variable model. But you are not using that anywhere in your code. I am not sure why you want to do that.
I am not sure why you are using session. If you are trying to pass data between your action method to view, there are other better solutions like using a viewmodel (preferred), ViewBag etc.
Remember Session data is available across the entire application for the current session., not just one page. Use it wisely.
In order to save your model to the Session, you need to set the session object first e.g.
using (DefaultConnection db = new DefaultConnection())
{
var model = from u in db.Users select u;
Session["User"] = model; //Part where you set / save into the session
var vm = Session["User"] as User; //Part where you retrieve into the session
return View(vm);
}
User user = Session["User"] as User;
if ( user == null) user = new User();
If you want to access your ViewModel on the view, you can do it in many ways one way is to associate your view to a model (known as strongly typed views). You can do this in your view:
#model type #*Associate your view to a ViewModel, where type is your ViewModel Class*#
<h1>#Model.Name</h1> #*access the properties of your view using #Model *#
#model is used to associate a model to a view while #Model is used to access the associated model of a view. I suggest you read first on how ASP.NET MVC works. You may visit the ASP.NET MVC tutorial on views

How to operate on the table many to many EF

I am working with ASP.NET MVC and I am using Entity Framework. While generating my database which has been created by DataBase First I got this relation which is shown below. My question is: how can I assign a role for a particular patient?
This slightly depends on how your project is structured, and any design patterns you're using, but the below code should point you in the right direction.
// query the DB for existing patient/role
var dbContext = new MyDbContext()
var patient = dbContext.Set<Patient>().FirstOrDefault(x => x.PatientID = patientId);
var role = dbContext.Set<Role>().FirstOrDefault(x => x.RoleID = roleId);
patient.Roles.Add(role);
dbContext.SaveChanges();
EDIT
Or something like this for a new instance of a patient...
var newPatient = new Patient {
Name = "NameHere"
....
};
newPatient.Roles.Add(role);
dbContext.Entry(newPatient).State = System.Data.EntityState.Added;
dbContext.SaveChanges();

How to get list of all ApplicationUsers who are in certain Role from database by LINQ expression?

I want to get:
list of ApplicationUsers who are in role "NormalUser" to anybody
list of all ApplicationUsers only to Admins only.
I did this:
// GET: ApplicationUsers
public ActionResult Index() {
// if you are Admin you will get all users
if (User.IsInRole("Admin"))
return View(db.Users.ToList());
//if you are somebody else(not Admin) you will see only list of NormalUsers
//HERE I GET ERROR
var list = db.Users.Where(x => UserManager.IsInRole(x.Id, "NormalUser")).ToList(); // here I get error
return View(list);
}
UserManager inside code above is: UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(db));
But unfortunately my LINQ expresiion is incorrect. I get error:
LINQ to Entities does not recognize the method 'Boolean IsInRole[ApplicationUser,String](Microsoft.AspNet.Identity.UserManager`2[WebApplication2.Models.ApplicationUser,System.String], System.String, System.String)' method, and this method cannot be translated into a store expression.
Question: How to correctly get list of users who are in role "NormalUser"?
The UserManager.IsInRole function isn't supported at the database, but if your application can bear the weight of pulling the whole User table back from the database before applying your filter then you can just add a ToList between your Users table reference and your Where filter, i.e.
var list = db.Users.ToList().Where(x => UserManager.IsInRole(x.Id, "NormalUser")).ToList();
I reached here for a good quick answer but could not find one. So decided to put on what I got for any other visitor who comes here. To get the List of Users in any particular Role, one can use this code.
public async Task<ActionResult> Index()
{
List<ApplicationUser> appUsers=new List<ApplicationUser>();
await Task.Run( () =>
{
var roleManager = new RoleManager<IdentityRole>( new RoleStore<IdentityRole>( db ) );
var adminRole=roleManager.FindByName("Admin");
appUsers = db.Users.Where( x => x.Roles.Any( s => s.RoleId == adminRole.Id ) ).ToList();
} );
return View( appUsers );
}
It would be useful to know how Roles and Application users relate.
If the user can only belong to one role, it would be fine for you to do something like this:
var list = db.Users.ToList().Where(x => x.Role == "NormalUser").ToList();
Id the user can be part of multiple roles, it would look something more like this:
var list = db.Users.ToList().Where(x => x.Roles.Contains("NormalUser")).ToList();
Hope this helps.

Using ASP.Net Membership, get all users

I'm trying to use Membership.GetAllUsers() to create a list of all of my users in the database. However, I have a model that I use that maps out the user properties (First Name, Last Name, Email, etc.).
How can I add all of the users into List<ManageUserViewModel>.
I've already tired:
List<ManageUserViewModel> model = Membership.GetAllUsers();
and then
MembershipUserCollection users = Membership.GetAllUsers();
List<ManageUserViewModel> model = new List<ManageUserViewModel>();
foreach (var item in users)
{
model.Add(item);
}
If you're explicit with the object type in the foreach loop, you'll be able to access the user object you're looking for.
For example:
var users = Membership.GetAllUsers();
var userList = new List<MembershipUser>();
foreach (MembershipUser user in users)
{
userList.Add(user);
}
Membership.GetAllUsers() returns a MembershipUserCollection which in practice is a list of MembershipUser, whereas you want a list of ManageUserViewModel which I assume is an internal class to your application.
You can use LINQ for this:
var model = Membership.GetAllUsers()
.Select(m =>
new ManageUserViewModel {/* set properties you need here */ }
)
.ToList();
Which is the equivalent of:
var users = Membership.GetAllUsers();
var model = new List<ManageUserViewModel>();
foreach (var item in users)
{
model.Add(new ManageUserViewModel { /* set properties here */});
}
I had the same challenge. mine was with vb not c# and .NEt version 4.5 using visual studio 2013.
I got all the solution from Microsoft website here
best of luck

Resources