2010-05-12 4 views
1

ASP.NET MVC의 기본 모델 바인더에 문제가 있습니다. 보기는 다음과 같이 HTML이 포함asp.net mvc 기본 모델 바인딩 문제

<input name="SubDTO[0].Id" value="1" type="checkbox"> 
<input name="SubDTO[1].Id" value="2" type="checkbox"> 

이 내 단순화 '모델'

public class SubDTO 
{ 
    public virtual string Id { get; set; } 
} 

public class DTO 
{ 
    public List<SubDTO> SubDTOs { get; set; } 

    public DTO() 
{ 
    SubDTOs = new List< SubDTO>(); 
} 
} 

이 모든 사용자가 선택하면 잘 작동 적어도 첫 번째 체크 박스 (SubDTO [0] .ID) . 컨트롤러는 잘 초기화 된/바인딩 된 DTO를 '수신'합니다. 그러나 첫 번째 확인란을 선택하지 않은 경우 (예 : SubDTO [1] .Id) 개체 SubDTO는 null입니다. 누군가이 '이상한'행동을 설명하고 그것을 극복 할 수 있습니까? 감사.

행복을 빌며, 기독교

PS :

컨트롤러는 다음과 같습니다

 [Transaction] 
     [AcceptVerbs(HttpVerbs.Post)] 
     public RedirectToRouteResult Create(DTO DTO) 
     { 
... 
} 

PPS :

내 문제는 내가 확인란을 선택하면 그 SubDTO [0] .Id, SubDTO [1] .Id, SubDTO [2] .Id SubDTO가 초기화됩니다. 하지만 SubDTO [1] .Id, SubDTO [2] .Id (첫 번째 것은 아닙니다!) 확인란을 선택하면 SubDTO가 null로 유지됩니다. 내가 게시 된 값을 (방화탄을 사용하여) 검사하고 그들은 게시됩니다! 이것은 기본 모델 바인더의 버그이거나 뭔가 빠져있을 수 있습니다.

+0

조치 코드도 게시 할 수 있습니까? – Lazarus

+0

ok done - ps를 참조하십시오. thanks – cs0815

+0

모델 바인더는 반환 값에서 객체의 속성 이름과 일치하는 값을 시도합니다. – Lazarus

답변

2

이 동작은 "의도적으로"html로입니다. 확인란을 선택하지 않으면 서버에 값이 전송되고 아무 것도 선택하지 않으면 아무 것도 전송되지 않습니다. 그래서 당신이 당신의 행동에 null을 얻는다면 당신은 게시 된 형태로 가치를 찾지 못할 것입니다. 당신이 두 값이 전송됩니다 확인란 만을 선택하면

<input name="SubDTO[0].Id" value="true" type="checkbox"> 
<input name="SubDTO[0].Id" value="false" type="hidden"> 
<input name="SubDTO[1].Id" value="true" type="checkbox">  
<input name="SubDTO[1].Id" value="false" type="hidden"> 

이러한 방법 :이 문제를 해결하는 방법은 같은 이름과 같은 체크 박스 AFTER 어떤 값으로 숨겨진 필드를 추가하는 것입니다 모델 바인더는 처음에만 사용됩니다. 체크 박스를 체크하지 않으면 숨겨진 필드 값만 전송되고 null 대신 액션에서 값을 가져옵니다.

+0

내 문제는 SubDTO [0] .Id, SubDTO [1] .Id, SubDTO [2] .Id 일이 선택되어있는 경우입니다. 하지만 SubDTO [1] .Id, SubDTO [2] .Id (첫 번째 것은 아닙니다!) 확인란을 선택하면 SubDTO가 null로 유지됩니다. 내가 게시 된 값을 (방화탄을 사용하여) 검사하고 그들은 게시됩니다! 그러므로 '설계 상'일 수는 없지만 기본 모델 바인더의 버그 여야합니다. – cs0815

+0

당신은 내가 그것을 받아들이도록 당신의 대답을 편집 한 것 같습니다. 감사! – cs0815

1

변경 마크 업이 다음과 같이 당신이 원하는 명확하지 않은 RedirectToRouteResult Create(SubDTO[0].id, SubDTO[1].id, ..., SubDTO[n].id)를 호출하는 것처럼, 당신이 원하는, 즉 원래의 마크 업에 의해 반환되는 무슨

<input name="SubDTOs" value="<%= SubDTO[0].Id %>" type="checkbox"> 
<input name="SubDTOs" value="<%= SubDTO[1].Id %>" type="checkbox"> 

매개 변수의 관련이없는 세트입니다, 배열로 반환하여 DTO 객체이므로 모든 체크 박스에 동일한 이름을 부여하면 함수에 대한 반환 값은 ID의 배열이됩니다.

편집

이 시도 :

당신은 각각의 인덱스 요소가 있는지 확인하기 위해 뭔가를 반환해야
<input name="SubDTO[0].Id" value="<%= SubDTO[0].Id %>" type="checkbox"> 
<input name="SubDTO[0].Id" value="false" type="hidden"> 
<input name="SubDTO[1].Id" value="<%= SubDTO[1].Id %>" type="checkbox"> 
<input name="SubDTO[1].Id" value="false" type="hidden"> 

, 나는 어떤 차이가 나는 문제 때문에 발생합니다 의심 'null'ID (예 : 0 또는 -1)를 사용하여 나중에 코드에서 처리하는 것이 좋습니다. 또 다른 대답은 맞춤형 모델 바인더 일 것입니다.

항상 문자열 배열을 사용하여 클래스에서 SubDTO 배열을 만드는 속성을 클래스에 추가하는 대체 옵션이 있습니다.그

+0

내가 할 수 : 목록 SubDTOs 내 DTO에서 사용 : <입력 이름 = "SubDTOs"값 = "1"유형 = "체크 박스"> <입력 이름 = "SubDTOs"값 = "2 "type ="checkbox "> 문제가 없습니다! 하지만 액세스 경로가 필요합니다 : SubDTO.Id. 무슨 뜻인지 안다면. 값은 실제 (동적) pimary 키이며 내 확인란은 html 도우미를 통해 생성됩니다. – cs0815

+0

아니, 무슨 뜻인지 모르겠다. "SubDTO [0] .Id"라는 문자열 리터럴을 체크 박스의 이름으로 사용하고 있습니다. 체크 박스는 위와 같이 SubDTO [0] .Id의 * value *를 반환하는 확인란입니다. 위의 코드를 사용하면 모델 바인더에 전달 된 "checked"SubDTO Id 배열을 얻을 수 있습니다. – Lazarus

+0

아이디어는 SubDTO [0]입니다.Id는 (List ) SubDTO의 첫 번째 객체의 ID에 확인란의 값을 할당합니다. 이것은 적어도 내가 이름 SubDTO [0] .Id와 그 값을 게시하는 한 잘 작동하는 것 같습니다! – cs0815

1

같은

public List<string> SubDTOIds 
{ 
    get { return SubDTO.Select(s=>s.Id).ToList(); } 
    set 
    { 
     SubDTOs = new List< SubDTO>(); 
     foreach (string id in value) 
     { 
      SubDTOs.Add(new SubDTO { Id = id }); 
     } 
    } 
} 

또는 뭔가 스캇 Hanselman은의 블로그에 this 게시물 이유를 설명 것이라 생각합니다. 관련 라인은 다음과 같습니다

The index must be zero-based and unbroken. In the above example, because there was no people[2], we stop after Abraham Lincoln and don’t continue to Thomas Jefferson.

따라서, 귀하의 경우 (체크 박스의 기본 동작으로 다른 사람에 의해 설명) 첫 번째 요소는 전체 컬렉션이 초기화되지 않는 반환되지 않습니다 때문이다.

+0

내 가정을 확인해 주셔서 감사합니다! +1 – Lazarus

+0

감사합니다. Lester 님, 이렇게 추측합니다. 위의 동작을 수행하기 위해 내 확인란의 대안이 있습니까? 감사! – cs0815