2012-06-07 7 views
2

문제Automapper 매핑 드롭 다운 메뉴

나는 현재 내 MVC 프로젝트에 자동 매핑을 추가하고 위해를 IEnumerable 나는 붙어입니다. 지금은 데이터베이스의 데이터를 나타내는 데 사용되는 User 모델이 있습니다. Edit 메서드가 호출 될 때 사용되는 EditUserModel에 해당 모델을 매핑해야합니다. EditUserModel에는 IEnumerable<SelectListItem> (드롭 다운 메뉴의 경우)으로 맵핑하는 방법을 알 수없는 것처럼 보입니다.

솔루션 시도

지금 현재 난 아무것도 구현하는 시도하지 않았습니다. 나는 어디에 IEnumerable<SelectListItem>에 대한 최고의 장소 또는 어디에 그것을 채울 수 있는지 잘 모르겠습니다. 지금 그것은 컨트롤러에 채워지고 있습니다.

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

EditUserModel.cs

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

Controller.cs

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; 

답변

5

을, 여기에 내가 야쿱의 대답에 코멘트에 대해 이야기 한 것입니다 Jakub의 솔루션은 중첩 된 속성에서 작동하지 않으므로 속성 경로가 단순하지 않은 경우 실제로 더 강력합니다.

+0

그래 IEnumerable 을 생성하는 데 사용 된 코드의 양을 줄였습니다. 그러나 매퍼는이를 해결할 수 없습니다. 이것은 컨트롤러에서 가장 좋은 방법입니다. EditUserViewModel model = Mapper.Map <사용자, EditUserViewModel> (사용자); model.Roles = context.Roles.ToSelectList (r => r.RoleID, r => r.Description); –

1

컨트롤러 귀하의 뷰 모델을 채울 수있는 완벽한 장소입니다.

당신이 확장 방법을 사용하여 배관 코드를 제거 할 수 있습니다

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

없이하는 말 : 공식적으로

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); 
+0

확인을 (이 정말 대답, 난 그냥 점을 정교하게하는 데 도움이되는 커뮤니티 위키로 게시하도록하겠습니다되지 않음). 그런 다음 매핑 프로세스에서 역할 필드를 무시해야합니까? –

+0

확장 메서드가 일반 람다가 아닌 표현 트리를 사용하는 이유는 무엇입니까? –

+0

@KirkWoll - 내가 Moq ;-)에서 찢어 –