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
,这将为您省去很多潜在的麻烦。要构造 SelectListItem
的 Value
,我会简单地将两个复合 ID 作为字符串附加(因为值无论如何都必须是字符串)。通过逗号等分隔符加入它们。然后,在 post 上,您可以获得 posted 值并用相同的分隔符将其拆分以取回您的两个 ID。显然,您还需要将它们都转换回 int
s。您只能 post 从 select 返回一个值,因此当涉及到复合键时,这确实是您唯一的选择。
我正在为我的应用程序构建一个 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
,这将为您省去很多潜在的麻烦。要构造 SelectListItem
的 Value
,我会简单地将两个复合 ID 作为字符串附加(因为值无论如何都必须是字符串)。通过逗号等分隔符加入它们。然后,在 post 上,您可以获得 posted 值并用相同的分隔符将其拆分以取回您的两个 ID。显然,您还需要将它们都转换回 int
s。您只能 post 从 select 返回一个值,因此当涉及到复合键时,这确实是您唯一的选择。