DropDownListFor 具有值列的复合键

DropDownListFor Composite Key with Value Column

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

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

RolePermission 视图模型如下所示:

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)。

我如何构建一个下拉列表,显示可能的权限值列表和select该特定权限的正确权限值?

以下生成下拉列表,但不 select 任何值。此外,不给每个下拉列表一个唯一的名称或 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>               
 }

这里的问题主要是句法问题。请记住,对于 DropDownListFor 和其他 *For 风格的助手,您传递的是 表达式 ,而不是某些内容的字面实例。然后,帮助器尝试解析该表达式以在输入上创建一个名称属性值,该值将(希望)在数据被 post 回传时绑定。显然,然后,做类似 Find 的事情是行不通的,因为没有办法将其转换为在 posting 之后在另一端发生同样的事情。相反,你应该这样做:

@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>   
}

现在,表达式足够具体,可以绑定到。

此外,将 PermissionValues 属性 更改为 IEnumerable<SelectListItem> 而不是使用 KeyValuePair。然后,无需手动创建 SelectList,这将为您省去很多潜在的麻烦。要构造 SelectListItemValue,我会简单地将两个复合 ID 作为字符串附加(因为值无论如何都必须是字符串)。通过逗号等分隔符加入它们。然后,在 post 上,您可以获得 posted 值并用相同的分隔符将其拆分以取回您的两个 ID。显然,您还需要将它们都转换回 ints。您只能 post 从 select 返回一个值,因此当涉及到复合键时,这确实是您唯一的选择。