2012-10-13 2 views
1

ViewModel이 (가) 컬렉션 인 경우 ViewModel 속성을 일치하는 ModelState.Key 값과 일치시킬 수 있습니까?ViewModel 컬렉션에 ModelState 키를 일치시키는 MVC

예 : 뷰 모델 항목 컬렉션을 편집하려면 extension found here을 사용하고 있습니다.

페이지의 필드 ID에 GUID를 추가합니다.

예 : 애완 동물의 목록

class Pets 
{ 
    string animal; 
    string name; 
} 

는, 생성 된 HTML 소스는 다음과 같이이다 :

<input name="Pets.index" autocomplete="off" value="3905b306-a9..." type="hidden"> 
<input value="CAT" id="Pets_3905b306-a9...__animal" name="Pets[3905b306-a9...].animal" type="hidden"> 
<input value="MR. PEPPERS" id="Pets_3905b306-a9...__name" name="Pets[3905b306-a9...].name" type="hidden"> 


<input name="Pets.index" autocomplete="off" value="23342306-b4..." type="hidden"> 
<input value="DOG" id="Pets_23342306-b4...__animal" name="Pets[23342306-b4...].animal" type="hidden"> 
<input value="BRUTICUS" id="Pets_23342306-b4...__name" name="Pets[23342306-b4...].name" type="hidden"> 

이이 게시물에 바인딩됩니다 때 그래서 ModelState는 모든 양식로드되는 전지. 지금까지

Pets[23342306-b4...].name 
Pets[23342306-b4...].animal 
Pets[3905b306-a9...].name 
Pets[3905b306-a9...].animal 

모든 좋은,하지만 난 하나가 같은 이름으로 존재하는 경우와 같은 일이, 새로운 동물을 추가하지 못할 어떤 비즈니스 로직 유효성 검사를하고있는 중이 야 : 는 ModelSTate.Keys에있다. 이 경우 오류가있는 입력 필드를 강조 표시 할 수 있어야합니다. 내 생성 함수가 실패 그렇다면

,이 같은 오류/키 값 쌍을 반환합니다

{ error = "Duplicate Name", key="name" } 

그래서 나는 적어도 속성은 문제의 원인이됩니다 지금 무엇을.

하지만 저장소 기능에서 뷰 필드 ID에 대해 알지 못하기 때문에 적절한 "ModelState"키 (이 경우에는 Pets [23342306-b4 ...]. name)와 키 "name"을 어떻게 일치시킬 수 있습니까? 또는 Pets [3905b306-a9 ...]. 이름)?

답변

0

적절한 표시/편집기 템플릿 컬렉션 (Html.DisplayFor(m => m.Pets) 또는 Html.EditorFor(m => m.Pets))을 표시하는 MVC의 기능에 내장 된 사용하면, MVC는 다음과 같이 렌더링 것 :

Pets[0].name 
Pets[0].animal 
Pets[1].name 
Pets[1].animal 

IEnumerable<Pets>에 매핑을 당신은 알고 첫 번째 항목의 인덱스가 0이고 두 번째 항목이 1 등입니다.

두 번째 항목에 오류가있는 경우 ModelState"Pets[1].name"과 같은 오류를 설정할 수 있습니다.

+0

나는 GUID를 사용하는 다른 도우미 메서드를 사용하는 이유는이 인라인 편집하고 사용자가 행을 제거 할 수 있습니다, 그래서 순서가 변경 될 수 있다는 점이다. 또한 행을 추가 할 수 있으므로 새로 추가 된 행 (ajax 호출에서 오는)에 고유 ID가 있는지 확인하는 데 GUID가 사용됩니다. – getit

+0

또한 ModelState에는 항목 목록이있을뿐만 아니라 다른 필드도 있습니다. 모델을 항상 더 많은 필드로 업데이트 할 수 있기 때문에 목록의 위치를 ​​계산하는 것은 안전하지 않습니다. 이는 해당 매핑을 깨뜨릴 것입니다. – getit

+0

그래, 우리 응용 프로그램을위한 MVC 그리드를 만들 때 비슷한 문제에 직면했다. 실제로 행을 삭제하는 대신 숨겨진 필드를 사용하여 행을 삭제 된 것으로 표시해야했으며 새 행을 추가 할 때 이전 행의 색인을 구문 분석하고 jquery를 사용하여 이름과 ID를 바꿔야했습니다. – Necros

0

내가 그렇듯이 Html.BeginCollectionItem 확장 메서드를 사용하는 경우 GUID를 사용하지 않고이 문제를 해결할 수있었습니다. 나는 동적 인 추가와 삭제가 필요하다. 그러나 나는 항상 내가 알고있는 아이템을 찾고 있었다. 나는 편집자에게 ID가있는 사람들이다. 따라서 GUID를 사용하는 대신 ID (uniqueId)를 아래 코드에 지정합니다. 나는 그것이 사람이라는 것을 알았 기 때문에 열쇠를 발견 할 수있었습니다 [234232]. 물론 새 항목을 추가하고 선택한 항목을 표시하지 않으면 해당 항목이 작동하지 않을 수 있습니다.

 public static IDisposable BeginCollectionItem(this HtmlHelper html, string collectionName, string uniqueId) 
    { 
     var idsToReuse = GetIdsToReuse(html.ViewContext.HttpContext, collectionName); 
     string itemIndex = idsToReuse.Count > 0 ? idsToReuse.Dequeue() : uniqueId; 

     // autocomplete="off" is needed to work around a very annoying Chrome behaviour whereby it reuses old values after the user clicks "Back", which causes the xyz.index and xyz[...] values to get out of sync. 
     html.ViewContext.Writer.WriteLine(string.Format("<input type=\"hidden\" name=\"{0}.index\" autocomplete=\"off\" value=\"{1}\" />", collectionName, html.Encode(itemIndex))); 

     return BeginHtmlFieldPrefixScope(html, string.Format("{0}[{1}]", collectionName, itemIndex)); 
    }