List View displaying Roles and Application User - c#

I am very new to MVC5 and am trying to display a List view of user details and the name of the role they are in. I have set up the roles using MVC Identity.
Below is my ViewModel
public class UserRoleViewModel
{
public string UserRoleVMId { get; set; }
public string Title { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
public string Email { get; set; }
public string Role { get; set; }
public bool AccountEnabled { get; set; }
}
And my controller:
public ActionResult Index()
{
var model = (from d in db.Users
select new UserRoleViewModel()
{
UserRoleVMId = d.Id,
Title = d.Title,
FirstName = d.FirstName,
Surname = d.Surname,
Email = d.Email,
AccountEnabled = d.AccountEnabled,
Role = d.Role.Name
}).ToList();
return View(model);
}
I am unsure of how to display the role name and am getting the error message
does not contain the definition for Role and no extension method Role
at
Role = d.Role.Name
Any help would be greatly appreciated
Thanks

You can use the GetRoles method :
viewModel.RolesForThisUser = UserManager.GetRoles(userId).ToList();
This is useful when you want to display the details of one user.
You should use The property Roles, since a user could have multiple roles:
public ActionResult Index()
{
using(var context = new IdentityDbContext()){
viewModel =
context.Users
.Include("Roles")
.Select(u =>
new UserRoleViewModel {
UserRoleVMId = u.Id,
Title = u.Title,
FirstName = u.FirstName,
Surname = u.Surname,
Email = u.Email,
AccountEnabled = u.AccountEnabled,
Role = u.Roles.First().Role.ToString()
}
).ToList();
}
return View(viewModel);
}

You can use this code
return view(db.Users.ToList());
and in your view on top use
#model IEnumerable<YourProjectName.Models.Users>
and use this foreach for show content
#foreach(var item in Model){<p>#item.Title</p> and etc }

Related

Get role list with associated users in ASP.NET Identity

I have a role. How can I find the list of users which have that role?
public ViewResult Index()
{
return View(roleManager.RoleList.ToList());
}
In this method I take the list of roles there have the user's UsersId. Now how to link it with my UserModel to take the UserName?
I am not so good in the LINQ, and can't find a good idea
In the result I want to make a table in the view
foreach (RoleModel role in Model)
{
<tr>
<td>#role.Id</td>
<td>#role.Name</td>
<td>#role.Description</td>
<td>
#if (role.Users == null || role.Users.Count == 0)
{
#: Нет пользователей в этой роли
}
else
{
//User name which have that role
}
</td>
</tr>
}
This is one of the miss design of ASP.NET Identity that there is no short cut way of getting the list of Roles with its associated Users. But you can get with some extra effort as follow:
public class RoleViewModel
{
public string RoleId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<UserViewModel> Users { get; set; }
}
public class UserViewModel
{
public string UserId { get; set; }
public string UserName { get; set; }
}
public ViewResult Index()
{
List<RoleViewModel> rolesWithUsers = new List<RoleViewModel>();
List<ApplicationRole> applicationRoles = RoleManager.Roles.Include(r => r.Users).ToList();
foreach (ApplicationRole applicationRole in applicationRoles)
{
RoleViewModel roleViewModel = new RoleViewModel()
{
RoleId = applicationRole.Id,
Name = applicationRole.Name,
Description = applicationRole.Description
};
List<UserViewModel> usersByRole = UserManager.Users.Where(u => u.Roles.Any(r => r.RoleId == applicationRole.Id))
.Select(u => new UserViewModel
{
UserId = u.Id,
UserName = u.UserName
}).ToList();
roleViewModel.Users = usersByRole;
rolesWithUsers.Add(roleViewModel);
}
return View(rolesWithUsers);
}
Now each role will have its associated users.
Note : From performance standpoint, above solution is not a good option. That's why its always better to use ASP.NET identity entities with your own DbContext instead of default IdenityStote.

can't get values in foreach from Viewbag mvc

I'm trying to get values from userList viewbag.i can't figure out the solution. Error is:
An exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in System.Core.dll but was not handled in user code
Additional information: 'object' does not contain a definition for 'name'
though in ViewBag.userList contains data (2 objects) which i can see while debugging
#foreach (var aUser in ViewBag.userList)
{
<tr>
<td>#aUser.name</td>
<td>#aUser.username</td>
.....
<td>#Html.ActionLink("Edit", "UserEdit","Users")</td>
<td>#Html.ActionLink("Delete", "UserDelete", "Users")</td>
</tr>
}
I have a superclass and a childclass
superclass
public partial class user
{
public int id { get; set; }
public string name { get; set; }
public string username { get; set; }
...
public string user_role { get; set; }
}
childclass
public class UserSub: user
{
public string CreatedUserName { get; set; }
public string ModifiedUserName { get; set; }
}
In my controller i used linq to get values from database and stored it to Viewbag.userList. My controller function is
public ActionResult UserList()
{
IEnumerable<user> users = null;
users = dbEntities.users.ToList();
if (users != null)
{
var userLists = (from a in users join b in users on a.created_user_id equals b.id select new { a.name, a.username, a.password, a.user_role, a.is_enable, a.is_approved, CreatedUserName = b.name, a.create_time, a.is_android, a.device_id }).ToList();
ViewBag.userList = userLists;
}
return View();
}
tried List<UserSub> users=ViewBag.userList....getting error too
Use a ViewModel to share data between view and controller.
For example, first create the ViewModel:
public class userViewModel{
public int id { get; set; }
public string name { get; set; }
public string username { get; set; }
public string user_role { get; set; }
public string CreatedUserName { get; set; }
public string ModifiedUserName { get; set; }
...
}
You can put all data that you need in your view model... Then, I'll recommend you create a class in your model with all the queries that you need (you have to investigate how to do), but you can get the queries from your controller (if you want).
Well, edit your controller function:
public ActionResult UserList()
{
List<userViewModel> userVM = new List<userViewModel>(); //Important! Don't return all the query, just the data that you need.
IEnumerable<user> users = null;
users = dbEntities.users.ToList();
if (users != null)
{
var userLists = (from a in users join b in users on a.created_user_id equals b.id select new { a.name, a.username, a.password, a.user_role, a.is_enable, a.is_approved, CreatedUserName = b.name, a.create_time, a.is_android, a.device_id }).ToList(); //I'm going to suppose that your query is ok and you get all the data that you need...
foreach (var item in userLists)
{
userVM.Add(new userVM(){
userVM.name = item.name;
userVM.username = item.username;
userVM.user_role = item.user_role;
.......
});
}
}
return View(userVM); //return your view model
}
Finally, modify your view and call the ViewModel userViewModel
#model Model.ViewModel.userViewModel //It depends on the namespace
//Then try something likes this...
#foreach (var aUser in Model)
{
<tr>
<td>#aUser.name</td>
<td>#aUser.username</td>
.....
<td>#Html.ActionLink("Edit", "UserEdit","Users")</td>
<td>#Html.ActionLink("Delete", "UserDelete", "Users")</td>
</tr>
}
That's the idea, improve my answer. ;)

How can i fill a value from one my domain model to my edit model?

In my project i have : countries and CountryEditModel.
public class countries
{
public int id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
}
public class CountryEditModel
{
public int id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public bool isvalid{ get;set; }
}
countries is my domain model which is binded with entity framework and countryEditModel is the model which i use in my views.
How can i fill values from countries to countryEditModel. I actually want to bind list of all countries to dropdownlist in my view and I don't want to use my countries domain model directly in my view.
To solve i have done this
var countryDomain = context.Country.Select(c => c).ToList();
var countrylist = new List<CountryEditModel>();
var countrymodel = new CountryEditModel();
foreach (var country in countryDomain)
countrymodel = new CountryEditModel()
{
Code = country.Code,
Name = country.Name,
id = country.id
};
countrylist.Add(countrymodel);
Is there any better way?
Answer:
Actually this is what i exactly wanted to do
var countryViewModel = context.Country.Select(c => new CountryEditModel
{
Code = c.Code,
Name = c.Name,
id = c.id
}).ToList();
As indicated by the #rohitsingh this is what he exactly wanted to do
var countryViewModel = context.Country.Select(c => new CountryEditModel
{
Code = c.Code,
Name = c.Name,
id = c.id
}).ToList();

WCF REST service doesn't return anything because I have a circular reference (I think)

I'm developing a WCF REST service using Entity Framework Code First data layer and I have a navigation property.
User class:
[DataContract]
public class User
{
[DataMember]
public int UserId { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public int Age { get; set; }
[DataMember]
public string City { get; set; }
[DataMember]
public string Country { get; set; }
[DataMember]
public string Email { get; set; }
[DataMember]
public string InterestIn { get; set; }
[DataMember]
public virtual ICollection<User> Friends { get; set; }
[DataMember]
public virtual ICollection<User> FromWhomIsFriend { get; set; }
}
ServiceContract method:
public List<User> GetUserFriends(string user_id)
{
int userId;
OutgoingWebResponseContext ctx =
WebOperationContext.Current.OutgoingResponse;
if ((user_id == null) ||
(!Int32.TryParse(user_id, out userId)) ||
(userId < 1))
{
ctx.StatusCode = System.Net.HttpStatusCode.BadRequest;
ctx.StatusDescription = "user_id parameter is not valid";
throw new ArgumentException("GetUserFriends: user_id parameter is not valid", "user_id");
}
List<User> friends = null;
try
{
using (var context = new AdnLineContext())
{
context.Configuration.ProxyCreationEnabled = false;
context.Configuration.LazyLoadingEnabled = false;
var users = from u in context.Users.Include("Friends")
where u.UserId == userId
select u;
if ((users != null) &&
(users.Count() > 0))
{
User user = users.First();
//friends = user.Friends.ToList();
friends = new List<User>();
foreach (User f in user.Friends)
{
User us = new User()
{
UserId = f.UserId,
Name = f.Name,
Age = f.Age,
City = f.City,
Country = f.Country,
Email = f.Email,
InterestIn = f.InterestIn,
Friends = f.Friends,
FromWhomIsFriend = f.FromWhomIsFriend
};
friends.Add(us);
}
}
ctx.StatusCode = System.Net.HttpStatusCode.OK;
}
}
catch (Exception ex)
{
ctx.StatusCode = System.Net.HttpStatusCode.InternalServerError;
ctx.StatusDescription = ex.Message;
ctx.SuppressEntityBody = true;
}
return friends;
}
This method doesn't return anything. If I comment this line FromWhomIsFriend = f.FromWhomIsFriend it works.
FromWhomIsFriend is a navigation property to the user from whom I am his friend. To represent user relationship I have this table:
UserID | FriendID
---------+----------
3 | 1
---------+----------
1 | 2
If I ask about friends from user 1, I get user 2, and its FromWhomIsFriend pointing to user 1. And user 1 Friends navigation property pointing to user 2, and continues.
Do you know how why I don't return anything?
You have to enable proxy creation in order to support the lazy loading. What you can do is to use Include in your query to load the navigation property .
var users = from u in context.Users.Include(u=>u.Friends)
where u.UserId == userId
select u;
Or else the other solution is using separate object model as the WCF contracts(DTO). Then you can enable lazy loading and then copy all the required values form the EF entity object(proxy) to your new Data Transfer Object. You can use something like Automaper to map the object easily.

How to print after join linq query

I have this code:
public ActionResult Index()
{
MembershipUser currentUser = Membership.GetUser();
Guid UserId = (Guid)currentUser.ProviderUserKey;
var users = from m in db.Users
join m2 in db.MyProfiles on m.UserId equals m2.UserId
where m.UserId == UserId
select new{UserName = m.UserName, LastActivityDate = m.LastActivityDate,
Address = m2.Address, City = m2.City, State = m2.State, Zip = m2.Zip};
return View(users);
}
This code is in my Controller, I want to run this query and then print the results into my view, how would I write the view?
//if your question is how to display(Print!) a view for above query then in ActionResult Index()
//1] As as best practise always Create a ViewModel - UserViewModel
public class UserviewModel
{
public string Username {get;set;}
public string Address {get;set;}
}
//2] Assign db.user values to UserviewModel or you can use Automapper
//and 3] then return this viewmodel to view
return View(UserviewModel);
This code cannot work because your LINQ query is returning an anonymous object so you cannot strongly type your view. So the first step would be to define a view model which will represent the information you are willing to display on your view:
public class UserViewModel
{
public string UserName { get; set; }
public DateTime LastActivityDate { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
}
then in your controller action you would return a collection of this view model:
public ActionResult Index()
{
var currentUser = Membership.GetUser();
var userId = (Guid)currentUser.ProviderUserKey;
var users =
from m in db.Users
join m2 in db.MyProfiles on m.UserId equals m2.UserId
where m.UserId == userId
select new UserViewModel
{
UserName = m.UserName,
LastActivityDate = m.LastActivityDate,
Address = m2.Address,
City = m2.City,
State = m2.State,
Zip = m2.Zip
};
return View(users);
}
and finally in your strongly typed view:
#model IEnumerable<AppName.Models.UserViewModel>
#Html.DisplayForModel()
and in the corresponding display template (~/Views/Shared/DisplayTemplates/UserViewModel.cshtml) which will be rendered for each item of the collection:
#model AppName.Models.UserViewModel
<div>
Username: #Html.DisplayFor(x => x.UserName)<br/>
Last activity: #Html.DisplayFor(x => x.LastActivityDate)<br/>
...
</div>
You need to get the type of users and make a List-View of that type. Easiest way to make a view is simply right-clicking in your controller method and selecting Create View. That'll make sure the routing gets done properly as well.

Categories