【问题标题】:Binding issue in a list at a complex model to an mvc application将复杂模型列表中的问题绑定到 mvc 应用程序
【发布时间】:2014-03-18 07:28:48
【问题描述】:

我是使用 .NET MVC Web 应用程序的新手。我正在使用 Web 应用程序的第 4 版。 我正在开发一个页面来管理简单会员提供者的角色,我希望它是动态的。为了清楚我的意思,它会是这样的:

事情就这么简单。为此,我有一个复杂的 ViewModel,例如:

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());
    }
}

在我看来,我有这样的东西来显示角色名称:

<th><strong>@Html.DisplayFor(m => m.AllRoleNames, "AllRoleNames")</strong></th>

而且,我有一个 DisplayTemplates 文件夹,其中包含 AllRoleNames.cshtml 文件,这是里面的内容(我还不担心页面的布局):

@model List<string>

@if (Model != null)
{ 
    for (int i = 0; i < Model.Count; i++)
    {
        @Html.HiddenFor(m => m[i])
        @Html.DisplayFor(m => m[i])
    } 
}

到目前为止,一切都很好。它正确显示名称。 但是,当我尝试按下 Save 按钮时,MVC 应该从 html 中获取正确的名称以绑定到我的 HTTP Post Controller Action 中的对象模型:

[HttpPost]
public ActionResult AdminUsers(UserInRolesModel model)
{
    //code to save roles goes here
    return View(model);
}

但我得到了一个空模型。 (我现在只是担心角色名称列表,因为一旦我弄清楚它发生了什么,我也可以弄清楚我的 UserInRoles 对象列表发生了什么)。

我可以找出为什么 MVC 没有正确绑定。因为生成的html是这样的:

<input id="AllRoleNames__0_" name="AllRoleNames.[0]" type="hidden" value="Admin">
Admin
<input id="AllRoleNames__1_" name="AllRoleNames.[1]" type="hidden" value="Extrator">
Extrator

名称属性正在生成为“AllRoleNames.[0]”,而它应该是“AllRoleNames[0]”。那里有一个额外的点。所以,我发现this question 带有答案提出的黑客攻击。它可以工作,但是当我测试时,我看到我的 HtmlFieldPrefix 已经没有点,所以它当然没有工作。

我的问题是,为什么 MVC 会用点生成这些名称,有没有办法告诉它正确生成?

【问题讨论】:

    标签: c# asp.net asp.net-mvc asp.net-mvc-4


    【解决方案1】:

    这是因为您使用的是for 循环而不是foreach,请在AllRoleNames 模板中尝试:

    foreach (var role in Model)
    {
        @Html.HiddenFor(m => role)
        @Html.DisplayFor(m => role)
    } 
    

    【讨论】:

    • 您好 Daniele,感谢您的回复。事实上,当我尝试使用 foreach 语句时,我摆脱了那个点。但它也摆脱了我的收藏,因为生成的代码类似于所有项目的“AllRoleNames.role”。你看到我失去了列表中的 [0]、[1] 吗?因此,当我回发时,它也不会绑定到模型。感谢您的回答,但它没有用......
    【解决方案2】:

    我发现传递一个列表作为模型只是痛苦。如果你传递一个包含 List 的类,生活就会变得容易得多。然后,您可以使用 for 循环,事情将开始按照您期望的方式运行。即

    for(int i = 0; i < model.MyList.Count; i++)
    {
        @Html.HiddenFor(model => model.MyList[i])
        @Html.DisplayFor(model  => model.MyList[i])
    } 
    

    应该正确生成您的属性名称。

    【讨论】:

    • 确实,PITaylor,我在模型中使用列表时没有得到很好的结果。因此,根据您的回答,我发现我可以处理我认为的所有内容,而无需 DisplayTemplate。所以,我只是按照你的建议在 for 循环中使用了类似 @Html.HiddenFor(m => m.AllRoleNames[i]) 的东西。此外,我使用相同的逻辑来显示用户权限的复选框。谢谢你的回答。
    • 没问题...我也必须自己努力学习。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-18
    • 2023-03-18
    • 2016-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多