I have a ListBox in a View displaying the possible choices. However, the user's role(s) are not shown as selected. In my UserViewModel the Roles collection contains the complete list of roles, and AspNetRoles collection contains only the roles to which the user belongs. I've tried multiple examples/variations but nothing ever shows as selected. I'm stuck.
ViewModel:
public class UserViewModel
{
public string Id { get; set; }
public string Email { get; set; }
public ICollection<AspNetRole> Roles { get; set; }
public virtual ICollection<AspNetRole> AspNetRoles { get; set; }
}
Controller:
public ActionResult Edit(string id)
{
UserViewModel user = new UserViewModel();
AspNetUser aspNetUser = new AspNetUser();
if (!string.IsNullOrEmpty(id))
{
aspNetUser = db.AspNetUsers.Find(id);
user.Id = aspNetUser.Id;
user.Email = aspNetUser.Email;
user.AspNetRoles = aspNetUser.AspNetRoles;
var roles = (from r in db.AspNetRoles
select r).ToList();
user.Roles = roles;
}
return View(user);
}
View:
#Html.ListBox("AspNetRoles",
new MultiSelectList(Model.Roles, "Id", "Name",
Model.AspNetRoles.Select(m => m.Id)))
You have not posted your model, but it appears that property AspNetRoles is a collection of a complex object (you cannot bind to a complex object, only a value type - or in the case of ListBox, a collection of value type). You can handle this by changing AspNetRoles to int[] (assuming the ID property of Role is int)
#Html.ListBoxFor(m => m.AspNetRoles, new SelectList(Model.Roles, "Id", "Name"))
Note, Its always better to use the strongly typed helpers.
Related
I have a ViewModel
public class ProductViewModel
{
public ProductModel Product { get; set; }
public string ProductVersion { get; set; }
public UserModel User { get; set; }
...
}
I query the database and fetch a Dataset which has one table say Table[0] that has- many rows- a list of details of all the members of my ViewModel (i.e. Product,ProductVersion,User)
My db query is as below
SELECT productName,
productID,
productPrice,
...
PRODUCTVerion,
UserName,
UserID,
UserEmail
FROM Product,
ProductVersionCtrl,
User
...
The return type of my method is
IEnumnerable of ProductViewModel
<>
My Requirement I need a lamda linq query that would frame\form the object IEnumnerable
of ProductViewModel
return type is given below
IEnumerable<ProductViewModel>
What I have tried
I have idea to place simple data which belongs to one complex object liek
IEnumerable<DealerModel> list = dsData.Tables[0].AsEnumerable().Select(p =>
new DealerModel()
{
DealerID = int.Parse(p["DealerID"].ToString()),
DealerName = p["DealerName"].ToString(),
DealerContactNo = p["DealerContactNo"].ToString(),
DealerEmailID = p["DealerEmailID"].ToString(),
DealerPassword = "******",
IsActive = int.Parse(p["IsActive"].ToString())
});
But I am not able to place different object within the ViewModel
Yes I got it , The below worked for me.
IEnumerable<ProductBuyViewModel> productBuyList = dsData.Tables[0].AsEnumerable().Select(p =>
new ProductBuyViewModel()
{
ProductBuy = {ProductName = p["productName "],ProductPrice =p["ProductPrice ...]},
ProductVesrion =p["ProductVesrion "],
User = {UserName =...}
});
I am working two database tables where UserDetaisl table holds details about Users having one or multiple Roles and Role table holds name of the Roles. I need to generate a HTML table something similar to the picture below. Where Each role from the Role table would be shown as a column and user with assigned role would be displayed as a check box ticked for that cell. non assigned role would show unticked check box. One user can have more than one role.
My classes look like:
public partial class UserDetails
{
public string username { get; set; }
public string role { get; set; }
public virtual Role Role1 { get; set; }
}
public partial class Role
{
public string Role1 { get; set; }
public virtual ICollection<UserDetails> UserDetails { get; set; }
}
Thought of creating a ViewModel which would show the Role selection.
public class RoleSelectionViewModel
{
public bool Selected { get; set; }
public bool NotSelected { get; set; }
public virtual Role Role1 { get; set; }
}
Not sure how to put all these toegther to generate the columns on the fly.
currentlty the following Controller method only lists all the users from the table with associated role.
public ActionResult Index()
{
var userDetails = db.UserDetails.Include(u => u.Role1);
return View(userDetails .ToList());
}
Your UserDetails class contains properties string role and virtual Role Role1 which means that a UserDetails can only contain one role. In order to select and assign multiple roles, then you model would need a public virtual ICollection<Role> Roles { get; set; } property.
In order to generate the view you want, you need to create view models
public class UserVM
{
public string UserName { get; set; }
public List<RoleVM> Roles { get; set; }
}
public class RoleVM
{
public string RoleName { get; set; }
public bool IsSelected { get; set; }
}
and your view would be
#model List<UserVM>
....
#using (Html.BeginForm())
{
<table>
<thead>....</thead>
<tbody>
#for(int i = 0; i < Model.Count; i++)
{
<tr>
<td>
#Html.DisplayFor(m => m[i].UserName)
#Html.HiddenFor(m => m[i].UserName)
</td>
#for(int j = 0; j < Model[i].Roles.Count; j++)
{
<td>
#Html.HiddenFor(m => m[i]Roles[j].RoleName)
#Html.CheckBoxFor(m => m[i]Roles[j].IsSelected)
</td>
}
</tr>
}
</tbody>
</table>
<input type="submit" ... />
}
Since the models you have shown are not correct for what your wanting to achieve, and I suspect you will need to makes changes to you data base (you will need tables for Users, Roles and UserRoles), the following controller code is a suggestion of what it should look like
public ActionResult Edit()
{
var roles = db.Roles; // get the collection of all roles
var users = db.Users.Include(x => x.Roles); // get the collection of all users including their selected roles
List<UserVM> model = new List<UserVM>();
foreach (var user in users)
{
UserVM u = new UserVM
{
UserName = user.username,
Roles = roles.Select(x => new RoleVM
{
RoleName = x.Role1
}).ToList()
}
.... // set the IsSelected property of each RoleVM based existing roles
model.Add(u);
}
return View(model);
}
[HttpPost]
public ActionResult Edit(List<UserVM> model)
{
// Get the selected roles for each user
foreach (UserVM user in Model)
{
var selectedRoles = user.Roles.Where(x =>x.IsSelected);
If you want the Users to have several Roles you will have to update your UserDetails class to have a Collection of Roles instead of just one.
Then update your RoleSelectionViewModel like
public class RoleSelectionViewModel
{
public ICollection<Role> Roles { get; set; } //list of all roles existing in your db for the columns
public ICollection<UserDetails> Users {get; set;} //list of all users for which you want to set roles
}
and then in the controller
public ActionResult Index()
{
var userDetails = db.UserDetails.Include(u => u.Roles).ToList();
var allRoles = db.Roles.ToList();
var viewModel = new RoleSelectionViewModel();
viewModel.Users = userDetails;
viewModel.Roles = allRoles;
return View(viewModel);
}
then you can Iterate over the Roles for the columns and over the users for the Rows and set the Checkboxes if the user has the role of the actual column.
I have two tables TxtComment and Login.
I am displaying image urls from Login table and comments from TxtComment table where username in TxtComment equals username in Login.
I am using Db First approach using entityframework.
How can I concatenate these columns from different tables to one common view? I used ViewBag. I got a result.
Controller
public ActionResult Item(int id)
{
FoodContext db = new FoodContext();
ViewBag.FoodItems = db.FoodItems.Where(row => row.itemid == id);
ViewBag.TxtComments = (from user in db.TxtComments
from ff in db.Logins
where ff.username == user.username
select new { imgurl = ff.imgurl, txtcmt = user.txtcmt });
return View();
}
View
#for(var item in ViewBag.TxtComments)
{
<div>#item</div>
}
The result is {imgurl=http:/sdfsdf,txtcmt=sfsdfsdf}
I need each item seperate. How can I? I tried with #item.imgurl, it says error. Is view bag is better? If not, please help me this need with strongly type view.
Create your own ViewModel instead of putting the model inside the ViewBag.
ViewModel:
public class ViewModel
{
public List<ImageComment> ImageComments { get; set; }
public ViewModel()
{
ImageComments = new List<ImageComment>();
}
}
public class ImageComment
{
public string ImageUrl { get; set; }
public string Comment { get; set; }
}
Controller Action:
public ViewResult Item(int id)
{
FoodContext db = new FoodContext();
List<ImageComment> comments = (from user in db.TxtComments
from ff in db.Logins
where ff.username == user.username
select new ImageComment
{
ImageUrl = ff.imgurl,
Comment = user.txtcmt
}).ToList();
ViewModel vm = new ViewModel{ ImageComments = comments };
return View("MyView", vm);
}
View:
#model ViewModel
#{
ViewBag.Title = "Comments";
}
#foreach(ImageComment comment in Model.ImageComments)
{
<p>#comment.Comment</p>
<img src="#comment.ImageUrl" alt="img" />
}
I am using C# in ASP MVC3. I have two tables from SQL Server.Table names are SMS_User and SMS_Division in SQL Server 2008. When i create a new user, I want to show division id from sms_division table.
SMS_User contains UserName, DivisionID, EmailAddress
SMS_Division contains DivisionID, DivisionName.
Controller Code :
UserController : Controller
{
private NetPerfMonEntities2 db = new NetPerfMonEntities2();
IEnumerableZamZam= db.SMS_Division.Select(c => new SelectListItem { Value = c.divisionid.ToString(), Text = c.divisionid.ToString() } );
}
When I create a new user in User Create() VIEW I want to show a DivisonName as a dropdown list instead of a text box. How I do that ?
#Html.DropDownListFor(model => model.divisionid, (IEnumerable<SelectListItem>) ViewData["Divisions"], "<--Select a divison-->")
#Html.ValidationMessageFor(model => model.divisionid)
I have this error message :
CS0103: The name 'sms_amountlimit2' does not exist in the current context
I'll be assuming a few missing part of your question in my answer, and give you a generic pattern to have a working dropdown list in ASP.NET MVC 3 :
Let's start with the models :
UserModel would be the class representing the data extracted from sms_user
public class UserModel
{
public string Username { get; set; }
public string EmailAddress { get; set; }
public int DivisionId { get; set; }
}
DivisionModel would be the class representing the data extracted from sms_division
public class DivisionModel
{
public int DivisionId { get; set; }
public string DivisionName { get; set; }
}
By Extracted, I mean anything that can transform the data in your Database in instanciated classes. That can be an ORM (EntityFramework or others), or SQL Queries, etc...
Next, is the viewmodel, because it wouldn't make sense to plug an IEnumerable of divisions in UserModel, and I personally don't really like using ViewData when I can avoid it :
public class UserViewModel
{
public UserModel User { get; set; }
public IEnumerable<DivisionModel> Divisions {get; set;}
}
Next, the controller :
public class UserController : Controller
{
public ActionResult Create()
{
List<DivisionModel> divisions = new List<DivisionModel>();
divisions.Add(new DivisionModel() { DivisionId = 1, DivisionName = "Division1" });
divisions.Add(new DivisionModel() { DivisionId = 2, DivisionName = "Division2" });
UserModel user = new UserModel() { Username = "testUser", EmailAddress = "testAddress#test.com" };
return View(new UserViewModel() { User = user, Divisions = divisions });
}
}
I just create the Division list and the user, but you would get then from you database by any means you are using.
And finally the View :
#model ViewModels.UserViewModel
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<p>
#Html.DropDownListFor(model => model.User.DivisionId, new SelectList(Model.Divisions, "DivisionId", "DivisionName"), "-- Select Division --")
#Html.ValidationMessageFor(model => model.User.DivisionId)
</p>
Note that the model binded to the view is the ViewModel.
In your model add a collection of the divisions then create the dropdown list like below:
#Html.DropDownListFor(m => m.SelectedDivisionId,
new SelectList(Model.Divisions, "DivisionId", "DivisionName"),
"-- Select Division --")
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.