C# 自动映射IEnumerable<;选择列表项>;用于下拉菜单
问题 我目前正在添加自动映射到我的MVC项目,我被卡住了。现在我有一个用于表示数据库中数据的用户模型。我必须将该模型映射到EditUserModel,调用Edit方法时将使用该模型。EditUserModel有C# 自动映射IEnumerable<;选择列表项>;用于下拉菜单,c#,asp.net,asp.net-mvc,viewmodel,automapper,C#,Asp.net,Asp.net Mvc,Viewmodel,Automapper,问题 我目前正在添加自动映射到我的MVC项目,我被卡住了。现在我有一个用于表示数据库中数据的用户模型。我必须将该模型映射到EditUserModel,调用Edit方法时将使用该模型。EditUserModel有IEnumerable(用于下拉菜单),我似乎不知道如何映射 尝试的解决方案 到目前为止,我还没有尝试实现任何东西。我不确定IEnumerable的最佳位置或填充位置。现在它正在控制器中填充 User.cs public class User { [Key] public
IEnumerable
(用于下拉菜单),我似乎不知道如何映射
尝试的解决方案
到目前为止,我还没有尝试实现任何东西。我不确定IEnumerable
的最佳位置或填充位置。现在它正在控制器中填充
User.cs
public class User
{
[Key]
public int UserID { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public int RoleID { get; set; }
[ForeignKey("RoleID")]
public virtual Role Role { get; set; }
}
public class EditUserViewModel
{
[HiddenInput(DisplayValue = false)]
public int UserID { get; set; }
[Required]
public String Username { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[DisplayName("Role")]
[Required]
public int RoleID { get; set; }
//The trouble field
public IEnumerable<SelectListItem> Roles { get; set; }
}
EditUserViewModel model = new EditUserViewModel();
//Population of the dropdown menu
model.Roles = context.Roles
.ToList()
.Select(x => new SelectListItem
{
Text = x.Description,
Value = x.RoleID.ToString()
});
//Mapping that the automaper will take care of
model.UserID = user.UserID;
model.Username = user.Username;
model.RoleID = user.RoleID;
EditUserModel.cs
public class User
{
[Key]
public int UserID { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public int RoleID { get; set; }
[ForeignKey("RoleID")]
public virtual Role Role { get; set; }
}
public class EditUserViewModel
{
[HiddenInput(DisplayValue = false)]
public int UserID { get; set; }
[Required]
public String Username { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[DisplayName("Role")]
[Required]
public int RoleID { get; set; }
//The trouble field
public IEnumerable<SelectListItem> Roles { get; set; }
}
EditUserViewModel model = new EditUserViewModel();
//Population of the dropdown menu
model.Roles = context.Roles
.ToList()
.Select(x => new SelectListItem
{
Text = x.Description,
Value = x.RoleID.ToString()
});
//Mapping that the automaper will take care of
model.UserID = user.UserID;
model.Username = user.Username;
model.RoleID = user.RoleID;
控制器是填充视图模型的理想场所 可以使用以下扩展方法删除卫浴代码:
public static class EnumerableExtensions
{
public static IEnumerable<SelectListItem> ToSelectList<T, TTextProperty, TValueProperty>(this IEnumerable<T> instance, Expression<Func<T, TTextProperty>> text, Expression<Func<T, TValueProperty>> value, Func<T, bool> selectedItem = null)
{
return instance.Select(t => new SelectListItem
{
Text = Convert.ToString(text.ToPropertyInfo().GetValue(t, null)),
Value = Convert.ToString(value.ToPropertyInfo().GetValue(t, null)),
Selected = selectedItem != null ? selectedItem(t) : false
});
}
public static PropertyInfo ToPropertyInfo(this LambdaExpression expression)
{
MemberExpression body = expression.Body as MemberExpression;
if (body != null)
{
PropertyInfo member = body.Member as PropertyInfo;
if (member != null)
{
return member;
}
}
throw new ArgumentException("Expression is not a Property");
}
}
model.Roles = context.Roles.ToSelectList(r => r.RoleID, r => r.Description);
公共静态类EnumerableExtensions
{
公共静态IEnumerable to SelectList(此IEnumerable实例,表达式文本,表达式值,Func selectedItem=null)
{
return instance.Select(t=>newselectListItem
{
Text=Convert.ToString(Text.ToPropertyInfo().GetValue(t,null)),
Value=Convert.ToString(Value.ToPropertyInfo().GetValue(t,null)),
Selected=selectedItem!=null?selectedItem(t):false
});
}
public static PropertyInfo ToPropertyInfo(此LambdaExpression表达式)
{
MemberExpression body=expression.body作为MemberExpression;
if(body!=null)
{
PropertyInfo成员=body.member作为PropertyInfo;
如果(成员!=null)
{
返回成员;
}
}
抛出新ArgumentException(“表达式不是属性”);
}
}
model.Roles=context.Roles.ToSelectList(r=>r.RoleID,r=>r.Description);
为了记录在案,以下是我在对Jakub答案的评论中所说的内容:
public static class EnumerableExtensions
{
public static IEnumerable<SelectListItem> ToSelectList<T, TTextProperty, TValueProperty>(this IEnumerable<T> instance, Func<T, TTextProperty> text, Func<T, TValueProperty> value, Func<T, bool> selectedItem = null)
{
return instance.Select(t => new SelectListItem
{
Text = Convert.ToString(text(t)),
Value = Convert.ToString(value(t)),
Selected = selectedItem != null ? selectedItem(t) : false
});
}
}
公共静态类EnumerableExtensions
{
公共静态IEnumerable ToSelectList(此IEnumerable实例,Func文本,Func值,Func selectedItem=null)
{
return instance.Select(t=>newselectListItem
{
Text=Convert.ToString(Text(t)),
Value=Convert.ToString(值(t)),
Selected=selectedItem!=null?selectedItem(t):false
});
}
}
不用说,这是非常简单的,并且实现了相同的功能(并且在属性路径不简单的情况下,实际上更加健壮,因为Jakub的解决方案将不适用于嵌套属性)
(这不是一个真正的答案,我把它作为一个社区wiki发布,只是为了帮助阐述一点)好的。那么,在映射过程中是否应该忽略角色字段?为什么扩展方法使用表达式树而不仅仅是普通的lambda?@KirkWoll-I从Moq中删除了它;-)嗯,好的。但这会让你的答案比需要的更加冗长。(您可以省去整个
ToPropertyInfo
方法)@KirkWoll-这就是我正在使用的代码。我粘贴了OP需要复制/粘贴才能使用的所有内容。好的,我看到这减少了用于生成IEnumerable的代码量。但是,映射程序无法解决此问题。因此,这是在控制器中执行此操作的最佳方法。EditUserViewModel模型=Mapper.Map(用户);model.Roles=context.Roles.ToSelectList(r=>r.RoleID,r=>r.Description);