Asp.net mvc 4 具有值列的复合键的DropDownList

Asp.net mvc 4 具有值列的复合键的DropDownList,asp.net-mvc-4,razor,dropdownlistfor,Asp.net Mvc 4,Razor,Dropdownlistfor,我正在为我的应用程序构建角色/权限组件。我的角色视图模型如下所示: public class RoleView { public int Id { get; set; } public ApplicationWithPermissionsView Application { get; set; } public List<RolePermissionView> Permissions { get; set; } public IEnumerabl

我正在为我的应用程序构建角色/权限组件。我的角色视图模型如下所示:

public class RoleView
{
    public int Id { get; set; }

    public ApplicationWithPermissionsView Application { get; set; }

    public List<RolePermissionView> Permissions { get; set; }

    public IEnumerable<KeyValuePair<string, int>> PermissionValues
    {
        get
        {
            return EnumHelper.ToList<PermissionValue>();
        }
    }

    [Required]
    public string Name { get; set; }
}
public class RolePermissionView
{
    public int PermissionId { get; set; }

    public int RoleId { get; set; }

    public PermissionValue Value { get; set; }
}
PermissionValue是一个枚举,其成员包括NotSet、Allow、Deny,并在数据库中存储int值

如果转到角色编辑页面,我会显示权限类别列表,每个类别都有一个权限列表,以及该角色的每个权限的相应值(RolePermission)。如您所见,RolePermissionView具有复合键(PermissionId,RoleId)

如何建立一个下拉列表,显示可能的权限值列表,并为该特定权限选择正确的权限值

下面将生成下拉列表,但不选择任何值。而且,并没有给每个下拉列表一个唯一的名称或ID,所以绑定肯定不起作用。我假设如果我以后将其移动到编辑器模板中,它们将具有唯一性

 @foreach (var permission in category.Permissions)
 {             
 <tr>                        
     <td>@permission.Description</td>                        
     <td>@Html.DropDownListFor(m => m.Permissions.Find(p => p.PermissionId == permission.Id).PermissionValue, new SelectList(Model.PermissionValues, "Value", "Key"))</td>
 </tr>               
 }
@foreach(category.Permissions中的var权限)
{             
@许可。描述
@DropDownListFor(m=>m.Permissions.Find(p=>p.PermissionId==permission.Id).PermissionValue,新选择列表(Model.PermissionValues,“Value”,“Key”))
}

这里的问题主要是语法问题。请记住,对于
DropDownListFor
和其他
*样式的帮助程序,您传递的是一个表达式,而不是某个内容的文本实例。然后,助手尝试解析该表达式,在输入上创建一个name属性值,该值将(希望)在数据发回时绑定。显然,像
Find
这样的操作是行不通的,因为没有办法将其翻译成同样的事情在发布后发生在另一端。相反,您应该执行以下操作:

@for (var i = 0; i < category.Permissions.Count(); i++)
{
    <tr>                        
        <td>@category.Permissions[i].Description</td>                        
        <td>@Html.DropDownListFor(m => category.Permissions[i].PermissionValue, Model.PermissionValues)</td>
    </tr>   
}
@for(var i=0;icategory.Permissions[i].PermissionValue,Model.PermissionValue)
}
现在,表达式足够具体,可以绑定到


另外,将
PermissionValues
属性更改为
IEnumerable
,而不是使用
KeyValuePair
。然后,无需手动创建
选择列表
,这将为您节省大量潜在的麻烦。要构造
SelectListItem
,我只需将两个复合ID作为字符串附加(因为该值无论如何都必须是字符串)。用逗号之类的分隔符将它们连接起来。然后,在post上,您可以获取post值,并用相同的分隔符将其拆分,以获取两个ID。显然,您还需要将它们都转换回
int
s。您只能从select返回一个值,因此这实际上是处理复合键时的唯一选项。

这里的问题主要是语法问题。请记住,对于
DropDownListFor
和其他
*样式的帮助程序,您传递的是一个表达式,而不是某个内容的文本实例。然后,助手尝试解析该表达式,在输入上创建一个name属性值,该值将(希望)在数据发回时绑定。显然,像
Find
这样的操作是行不通的,因为没有办法将其翻译成同样的事情在发布后发生在另一端。相反,您应该执行以下操作:

@for (var i = 0; i < category.Permissions.Count(); i++)
{
    <tr>                        
        <td>@category.Permissions[i].Description</td>                        
        <td>@Html.DropDownListFor(m => category.Permissions[i].PermissionValue, Model.PermissionValues)</td>
    </tr>   
}
@for(var i=0;icategory.Permissions[i].PermissionValue,Model.PermissionValue)
}
现在,表达式足够具体,可以绑定到


另外,将
PermissionValues
属性更改为
IEnumerable
,而不是使用
KeyValuePair
。然后,无需手动创建
选择列表
,这将为您节省大量潜在的麻烦。要构造
SelectListItem
,我只需将两个复合ID作为字符串附加(因为该值无论如何都必须是字符串)。用逗号之类的分隔符将它们连接起来。然后,在post上,您可以获取post值,并用相同的分隔符将其拆分,以获取两个ID。显然,您还需要将它们都转换回
int
s。您只能从select返回一个值,因此这实际上是您在复合键方面的唯一选择。

谢谢您的回复。我正在研究一种类似的方法。需要注意的一点是类别。权限只是特定类别的权限列表。Permissions是角色的PermissionRoles(组合键)列表。所以以上这些对我来说不太合适。KeyValuePair是因为我从一个枚举生成了一个更有用的列表。对此进行了一段时间的处理,它至少显示了值,给出了唯一的名称,并选择了一个选定的值(不过,我必须填充SelectList的第三个参数“objectSelected”)。我现在称之为胜利。谢谢你的回复。我正在研究一种类似的方法。需要注意的一点是类别。权限只是特定类别的权限列表。Permissions是角色的PermissionRoles(组合键)列表。所以以上这些对我来说不太合适。KeyValuePair是因为我从一个枚举生成了一个更有用的列表。对此进行了一段时间的处理,它至少显示了值,给出了唯一的名称,并选择了一个选定的值(不过,我必须填充SelectList的第三个参数“objectSelected”)。我现在称之为胜利。