Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding issue in a list at a complex model to an mvc application

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:

UsersInRoles

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?

like image 955
strongwind Avatar asked Oct 20 '22 14:10

strongwind


1 Answers

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.

like image 191
PlTaylor Avatar answered Oct 23 '22 03:10

PlTaylor