2010-05-26 4 views
1

일부 특수한 경우에는 런타임 전에 id를 모르는 텍스트 상자 (n - n 연관을 처리하기 위해) 목록이 필요합니다. 다음과 같이 표시됩니다. http://screencast.com/t/YjIxNjUyNmUASP.Net MVC 2 - 사전을위한 ModelBinding 더 <int, int>

해당 샘플에서는 필자는 '템플릿'중 일부에 카운트를 연결하려고합니다.

ASP.Net MVC 1에 나는 깨끗하고 직관적 인 HTML을 위해 사전 ModelBinder를 코딩. 여기
// loop on the templates 
foreach(ITemplate template in templates) 
{ 
     // get the value as text 
     int val; 
     content.TryGetValue(template.Id, out val); 
     var value = ((val > 0) ? val.ToString() : string.Empty); 

     // compute the element name (for dictionary binding) 
     string id = "cbts_{0}".FormatMe(template.Id); 
%> 
     <input type="text" id="<%= id %>" name="<%= id %>" value="<%= value %>" /> 
     <label for="<%= id %>"><%= template.Name %></label> 
     <br /> 

바인더의 코드입니다 : 그것은이 같은 것들을 허용

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
{ 
    IDictionary<int, int> retour = new Dictionary<int, int>(); 

    // get the values 
    var values = bindingContext.ValueProvider; 
    // get the model name 
    string modelname = bindingContext.ModelName + '_'; 
    int skip = modelname.Length; 

    // loop on the keys 
    foreach(string keyStr in values.Keys) 
    { 
     // if an element has been identified 
     if(keyStr.StartsWith(modelname)) 
     { 
      // get that key 
      int key; 
      if(Int32.TryParse(keyStr.Substring(skip), out key)) 
      { 
       int value; 
       if(Int32.TryParse(values[keyStr].AttemptedValue, out value)) 
        retour.Add(key, value); 
      } 
     } 
    } 
    return retour; 
} 

ASP.Net MVC 2에 전달 문제가 ValueProvider입니다하지 않는 더 이상 사전. 내가했던 것처럼 값을 반복하여 분석 할 방법이 없습니다.

나는 그렇게 할 수있는 다른 방법을 찾지 못했습니다.

마침내 사전을 바인딩하는 '표준'방식으로 바뀌었지만 HTML은보기 흉한 직관력이 떨어졌습니다 (색인 생성되지 않은 모음을 반복하는 카운터 사용). 그리고 모든 값은 필요하지 않습니다. 필요 (그리고 그것은 ASP.Net MVC 1에서 완벽하게 작동했습니다).

그것은 다음과 같습니다

int counter= 0; 
// loop on the templates 
foreach(ITemplate template in templates) 
{ 
     // get the value as text 
     int val; 
     content.TryGetValue(template.Id, out val); 
     var value = ((val > 0) ? val.ToString() : string.Empty); 

     // compute the element name (for dictionary binding) 
     string id = "cbts_{0}".FormatMe(template.Id); 
     string dictKey = "cbts[{0}].Key".FormatMe(counter); 
     string dictValue = "cbts[{0}].Value".FormatMe(counter++); 
%> 
     <input type="hidden" name="<%= dictKey %>" value="<%= template.Id %>" /> 
     <input type="text" id="<%= id %>" name="<%= dictValue %>" value="<%= value %>" /> 
     <label for="<%= id %>"><%= template.Name %></label> 
     <br /> 

을 나는 오류를 '값이 필요합니다'방지하기 위해 ModelState 트릭을 필요로하는 컨트롤러에서 :

public ActionResult Save(int? id, Dictionary<int, int> cbts) 
{ 
    // clear all errors from the modelstate 
    foreach(var value in this.ModelState.Values) 
     value.Errors.Clear(); 

이 너무 까다 롭습니다. 이 종류의 바인딩을 여러 번 사용할 필요가 있으며 응용 프로그램에서 개발자가 작업 할 수 있습니다.

질문 :

  • 당신이 그것을 더 잘 만들 수있는 방법을 알고 계십니까?

IMO는 더 나은 html을 허용하고 모든 값이 필요하다고 간주하지 않는 사전 용 ModelBinder입니다.

답변

2

MVC 2에서 MVC 1 모델 바인더를 계속 사용할 수 있습니다. 가장 큰 변화는 모델 바인더가 IValueProvider와 충돌해서는 안되며 요청 대신 직접 이동해야한다는 것입니다. 형태. 해당 컬렉션을 열거하고 특정 시나리오에 필요한 모든 논리를 수행 할 수 있습니다.

IValueProvider 인터페이스의 목적은 데이터의 출처를 추상화하고 범용 바인더 (예 : DefaultModelBinder)를위한 것입니다. 데이터가 열거 가능하다는 보장이 없기 때문에 IValueProvider 자체는 IEnumerable 일 수 없습니다. 그러나 특정 시나리오에서 특정 바인더를 사용하고 데이터가 양식에서 나오는 것을 알고있는 특별한 경우에는 추상화가 필요하지 않습니다.이 글이 도움이 될 것입니다 생각

+0

귀하의 조언에 감사드립니다. 언젠가 다시 기초로 돌아가는 것이 핵심이고, 당신이 그것을 볼 수없는 것은 아주 명백합니다 ... – Mose