I'm new using .NET MVC Web Application. I'm using the version 4 of Web Application. I'm developing a page to manage the roles of the simple membership provider, and I want to it be dynamically. To clear what I mean, it would be something like this:
Something really simple as that. To do so, I have a complex ViewModel such as this:
public class UserInRolesModel
{
public List<string> AllRoleNames { get; set; }
public List<UserInRoles> UsersInRoles { get; set; }
public UserInRolesModel()
{
AllRoleNames = new List<string>();
UsersInRoles = new List<UserInRoles>();
}
public UserInRolesModel(List<string> allRoleNames, List<UserInRoles> usersInRoles)
{
AllRoleNames = allRoleNames;
UsersInRoles = usersInRoles;
}
}
public class UserInRoles
{
public UserInRoles(string user, List<string> userRoles, IEnumerable<string> allRoleNames)
{
User = user;
Roles = SetRoles(userRoles, allRoleNames);
}
private List<bool> SetRoles(List<string> userRoles, IEnumerable<string> allRoleNames)
{
return allRoleNames.Select(userRoles.Contains).ToList();
}
public string User { get; set; }
public List<bool> Roles { get; set; }
public void UpdateRoles(List<string> allRoleNames)
{
var roleProvider = (SimpleRoleProvider)System.Web.Security.Roles.Provider;
var rolesAdded = new List<string>();
for (int i = 0; i < Roles.Count; i++)
{
if (Roles[i])
{
rolesAdded.Add(allRoleNames[i]);
}
}
roleProvider.AddUsersToRoles(new[] { User }, rolesAdded.ToArray());
}
}
In my View, I have something like this to display the role names:
<th><strong>@Html.DisplayFor(m => m.AllRoleNames, "AllRoleNames")</strong></th>
And, I have a DisplayTemplates Folder, with the AllRoleNames.cshtml file in it, and here is what's inside (I'm not worried about the layout of the page yet):
@model List<string>
@if (Model != null)
{
for (int i = 0; i < Model.Count; i++)
{
@Html.HiddenFor(m => m[i])
@Html.DisplayFor(m => m[i])
}
}
So far, so good. It displays the name correctly. But, when I try to press the Save button, the MVC should get the proper names from the html to bind to object Model in my HTTP Post Controller Action:
[HttpPost]
public ActionResult AdminUsers(UserInRolesModel model)
{
//code to save roles goes here
return View(model);
}
But I get an empty model. (I'm just worried to the list of roles name for now, because once I figure out what's happening with it, I can also figure out what's happening with my list of UserInRoles object).
I could find out why the MVC is not binding correctly. It's because the html generated is something like this:
<input id="AllRoleNames__0_" name="AllRoleNames.[0]" type="hidden" value="Admin">
Admin
<input id="AllRoleNames__1_" name="AllRoleNames.[1]" type="hidden" value="Extrator">
Extrator
The name attribute is being generated as "AllRoleNames.[0]" when it should be "AllRoleNames[0]". There is an extra dot there. So, I found this question with a hack proposed by the answer. It could work, but when I tested, I saw that my HtmlFieldPrefix already was without the dot, so of course it didn't work.
My question is, why is MVC generating these names with the dots, and is there a way to tell it to generate it correctly?
I have found that passing a List as the model is nothing but pain. If you pass a class that contains the List life becomes much easier. You can then use a for loop and things will start behaving the way you expect them to. i.e.
for(int i = 0; i < model.MyList.Count; i++)
{
@Html.HiddenFor(model => model.MyList[i])
@Html.DisplayFor(model => model.MyList[i])
}
should yield your property names correctly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With