can't get values in foreach from Viewbag mvc - c#

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. ;)

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.

Select 2 Column of 2 Table

I have 2 tables:
Staff: (ID, NAME)
Salary: (ID, VALUE)
My problem is:
How could I write in query syntax and method syntax in controller and return to the View(), like this in SQL query:
select a.NAME, b.VALUE
from Staff a, Salary b
where a.ID = b.ID
How could I declare in view like:
#model IEnumerable<Project.Model.xxxx>
This is the way I do with one table in IndexController:
LinQDataContext data = new LinQDataContext();
public ActionResult Index(int id)
{
var staffWithTheirSalary = data.Staff
.Select(a => a)
.Where(a => a.ID == id);
}
Index view:
#model IEnumerable<Project.Model.Staff>
#foreach(var item in Model)
{
#item.Name
}
You can have your view model to be IEnumerable<StaffSalaryViewModel> where StaffSalaryViewModel is:
public class StaffSalaryViewModel
{
public int StaffId { get; set; }
public string Name { get; set; }
public decimal Salary { get; set; } // Not sure of the type
}
Then to extract the list:
Using Linq method syntax:
var result = data.Staff
.Join(data.Salary,
staff => staff.ID,
salary => salary.ID,
(staff, salary) => new StaffSalaryViewModel {
StaffId = staff.ID,
Name = staff.NAME,
Salary = salary.VALUE
});
Using Linq query syntax:
var result = from staff in data.Staff
join salary in data.Salary on staff.ID equals salary.ID
select new StaffSalaryViewModel {
StaffId = staff.ID,
Name = staff.NAME,
Salary = salary.VALUE
};
UPDATE
It looks like the VALUE field in your Salary table allows null values. If so just make the corresponding property in your view model nullable, like so (provided it is a decimal type):
public class StaffSalaryViewModel
{
public int StaffId { get; set; }
public string Name { get; set; }
public decimal? Salary { get; set; } // Nullable/optional decimal
}
Or if you want to set StaffSalaryViewModel.Salary to 0 If VALUE is null, change your query to have:
Salary = salary.VALUE ?? 0
Because tables are being joined, I prefer using the query syntax. The controller would use the LinQDataContext to get at the data, but when creating the C# Object I would recommend creating a Class that is only used for displaying the data (in the example its called MySalaryModel).
public ActionResult Index(int id)
{
IEnumerable<Project.Model.MySalaryModel> staffWithTheirSalary = from staff in data.Staff
join salary in data.Salary on staff.Id equals salary.Id
select new Project.Model.MySalaryModel
{
Id = staff.Id,
Name = staff.Name,
Salary = salary.Value,
};
return View(staffWithTheirSalary);
}
use ViewModel,
you can create Viewmodel Folder in project and Create class into like this.
public class StaffSalaryViewModel
{
public int StaffId { get; set; }
public int SalaryeId { get; set; }
public string StaffName { get; set; }
public string SlaaryName { get; set; }
}
in action :
public ActionResult Index(int id)
{
StaffSalaryViewModel staffWithTheirSalary = (from itemStaff in data.Staff join itemSalary in data.Salary in itemStaff.id equal itemSalary.id where itemSalary.id=id select new StaffSalaryViewModel {Salaryname=itemSalary.Name,StaffName=itemStaff.Name,SalaryId=itemSalary.Id,itemStaff.Id}).ToList();
}
in View
#model IEnumerable<Project.ViewModel.StaffSalaryViewModel>
#foreach(var item in Model)
{
#item.SalaryName
}

C# - The entity or complex type cannot be constructed in a LINQ to Entities query

I'm trying to send data with a view and print it out, but I'm struggling really hard since I'm very new to C#.
So here's my model ViewModel:
namespace P104.Models
{
public class ViewModel
{
}
public class Location
{
public int loc_id { get; set; }
public string loc_name { get; set; }
}
public class Competentie
{
public int Comp_id { get; set; }
public string competentie { get; set; }
}
public class MyViewModel
{
public User User { get; set; }
public IEnumerable<Locations> Locations { get; set; }
public IEnumerable<Competenties> Competenties { get; set; }
}
}
This is the function I have in the controller
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
User user = db.user.Find(id);
if (user == null)
{
return HttpNotFound();
}
var competenties =
from usercomp in dbE.UserComp
join comp in dbE.Competenties on usercomp.fk_Comp_id equals comp.comp_id
where usercomp.fk_user_id == id
select new Competenties { competentie = comp.competentie };
var locations =
from userloc in dbE.UserLoc
join loc in dbE.Locations on userloc.fk_location_id equals loc.loc_id
where userloc.fk_user_id == id
select new Locations { loc_name = loc.loc_name };
var model = new MyViewModel
{
User = user,
Locations = locations.ToList(), // eagerly fetch the data that will be needed in the view
Competenties = competenties.ToList(), // eagerly fetch the data that will be needed in the view
};
return View(model);
}
And he's how I try to print it out in the view:
#foreach (var location in Model.Locations)
{
<dt>#location.locname</dt>
<dd>#location.locname</dd>
}
#foreach (var competentie in Model.Competenties)
{
<dt>#competentie.competentie</dt>
<dd>#competentie.competentie</dd>
}
I always recevie this error
The entity or complex type 'P104.Models.Locations' cannot be
constructed in a LINQ to Entities query.
I've found a few solutions, but I'm struggling to apply them to my code so they don't work.
Thanks in advance for your help
You seem to have got a typo here:
select new Locations { loc_name = loc.loc_name };
This should be:
select new Location { loc_name = loc.loc_name };
The model you are projecting against is called Location, not Locations. It's unclear what the Locations model is since you haven't shown that in your question.
And of course adapt your view accordingly:
#foreach (var location in Model.Locations)
{
<dt>#location.loc_name</dt>
<dd>#location.loc_name</dd>
}
By the way I will recommend you following standard C# naming conventions. This convention dictates that in C# a property name should start with an uppercase letter and not contain _. So basically you would rather use LocationName or just Name instead of loc_name. Same remark for your Competentie model.

List View displaying Roles and Application User

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 }

Cannot initialize type "x" with a collection initializer because it does not implement 'System.Collections.IEnumerable'

I am trying to join 3 tables using linq to sql and a ViewModel, pass the query to the View and display the results, but it doesn't work.
Update
DbContext Class:
public partial class DbEntities : DbContext
{
public DbSet<Foo> Foos{ get; set; }
public DbSet<Bar> Bars{ get; set; }
public DbSet<Fubar> Fubars{ get; set; }
}
ViewModel:
public class MyViewModel
{
public Foo Foo{ get; set; }
public Bar Bar{ get; set; }
public Fubar Fubar{ get; set; }
}
Controller:
public ActionResult Index(string searchString)
{
//var db = new MyViewModel(); //wrong
var db = new DbEntities();
var query = (from f in db.Foos
join b in db.Bars on f.IDFoo equals b.IDFoo
join fb in db.Fubars on b.IDBar equals fb.IDBar
select new MyViewModel {
f.IDFoo,
f.NameFoo,
f.CityFoo,
b.NameBar,
fb.NameFubar });
if (!String.IsNullOrEmpty(searchString))
{
query = query.Where(x => x.NameFubar.Contains(searchString));
}
return View(query);
}
View:
#model IEnumerable<Proj.Models.MyViewModel>
#using (Html.BeginForm())
{
<p>
#Html.TextBox("SearchString")
<input type="submit" class="no-button" value="Search" />
</p>
}
#foreach (var item in Model)
{
<div class="title">#Html.DisplayFor(modelItem => item.NameFubar)</div><br />
...
}
I get the following error:
1. "Cannot initialize type 'Proj.Models.MyViewModel' with a collection initializer because it does not implement 'System.Collections.IEnumerable' "
The problem was I had to set proprieties not classes in MyViewModel:
public short IDFoo { get; set; }
public string NameFoo { get; set; }
public string CityFoo { get; set; }
public string NameBar { get; set; }
public string NameFubar { get; set; }
And in the linq query I was using the collection initializer not the object initializer:
select new MyViewModel {
IDFoo = f.IDFoo,
NameFoo = f.NameFoo,
CityFoo = f.CityFoo,
NameBar = b.NameBar,
NameFubar = fb.NameFubar
};
This doesn't make much sense. You are creating a new instance of your view model, MyViewModel where navigation properties are not enumerables (!) and try to join on these?
Shouldn't you rather start with an instance of your db context? I do believe you should.
var db = new SomethingThatIsADbContext();
var query = (from f in db.Foos
join b in db.Bars on f.IDFoo equals b.IDFoo
join fb in db.Fubars on b.IDBar equals fb.IDBar
select new MyViewModel {
f.IDFoo,
f.NameFoo,
f.CityFoo,
b.NameBar,
fb.NameFubar }).ToList();
if you write this
query = query.Where(x => x.NameFubar.Contains(searchString));
performance very bad, you can where in your linq code.

Categories