2012-07-02 3 views
1

내 페이지 중 하나에 대해 상당히 복잡한 모델이 있습니다. 여러 개의 중첩 된 모델 객체로 구성됩니다. 자식 컬렉션 자식 객체를 사용하여 하나 개의 섹션에서, 내가 지금처럼 EditorFor 도우미를 사용MVC3 : 그래프에서 모델 속성의 위치를 ​​도우미로 알리기.

@Html.EditorFor(m => m.CAS.LERoles[i].LE, "TinyText") 

, 나는 같은 것을 끝낼 것이다

<input id="CAS_LERoles_0__LE" class="tinyText" type="text" value="0" name="CAS.LERoles[0].LE" data-val-required="The Legal Entity field is required." data-val-number="The field Legal Entity must be a number." data-val="true"> 

...이 중대하다 . 하지만 다음과 같이 목록을 선택하는 열거 형을 변환하는 내 자신의 도우미를 썼다 :

public static HtmlString EnumSelectListFor<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper, 
    Expression<Func<TModel, TProperty>> forExpression, 
    object htmlAttributes, 
    bool blankFirstLine) 
    where TModel : class 
    where TProperty : struct 
{ 
    //MS, it its infinite wisdom, does not allow enums as a generic constraint, so we have to check here. 
    if (!typeof(TProperty).IsEnum) throw new ArgumentException("This helper method requires the specified model property to be an enum type."); 

    //initialize values 
    var metaData = ModelMetadata.FromLambdaExpression(forExpression, htmlHelper.ViewData); 
    var propertyName = metaData.PropertyName; 
    var propertyValue = htmlHelper.ViewData.Eval(propertyName).ToStringOrEmpty(); 

    //build the select tag 
    var returnText = string.Format("<select id=\"{0}\" name=\"{0}\"", HttpUtility.HtmlEncode(propertyName)); 
    if (htmlAttributes != null) 
    { 
     foreach (var kvp in htmlAttributes.GetType().GetProperties() 
      .ToDictionary(p => p.Name, p => p.GetValue(htmlAttributes, null))) 
     { 
      returnText += string.Format(" {0}=\"{1}\"", HttpUtility.HtmlEncode(kvp.Key), 
       HttpUtility.HtmlEncode(kvp.Value.ToStringOrEmpty())); 
     } 
    } 
    returnText += ">\n"; 

    if (blankFirstLine) 
    { 
     returnText += "<option value=\"\"></option>"; 
    } 

    //build the options tags 
    foreach (var enumName in Enum.GetNames(typeof(TProperty))) 
    { 
     var idValue = ((int)Enum.Parse(typeof(TProperty), enumName, true)).ToString(); 
     var displayValue = enumName; 

     // get the corresponding enum field using reflection 
     var field = typeof(TProperty).GetField(enumName); 
     var display = ((DisplayAttribute[])field.GetCustomAttributes(typeof(DisplayAttribute), false)).FirstOrDefault(); 
     var titleValue = string.Empty; 
     if (display != null) 
     { 
      // The enum field is decorated with the DisplayAttribute => 
      // use its value 
      displayValue = display.Name; 
      titleValue = display.Description.ToStringOrEmpty(); 
     } 

     returnText += string.Format("\t<option value=\"{0}\" title=\"{1}\"", 
      HttpUtility.HtmlEncode(idValue), HttpUtility.HtmlEncode(titleValue)); 
     if (enumName == propertyValue) 
     { 
      returnText += " selected=\"selected\""; 
     } 
     returnText += string.Format(">{0}</option>\n", HttpUtility.HtmlEncode(displayValue)); 
    } 

    //close the select tag 
    returnText += "</select>\n"; 
    return new HtmlString(returnText); 
} 

을하고 내가 그렇게처럼 내 페이지에서 이것을 사용할 때 :

@Html.EnumSelectListFor(m => m.CAS.LERoles[i].APMasterRole) 

나는이와 끝까지 :

<select name="APMasterRole" id="APMasterRole"> 
(stuff) 
</select> 

나는 회상하면 적절하게 번역 될 것이라고 생각하고 이제는 조금 천진난하다는 것을 알았습니다. 적절한 이름과 ID를 생성하는 데 사용할 수있는 MVC 프레임 워크에 내장 된 메커니즘이 정말로 필요합니다. 그렇지 않으면 이것이 반성의 미로처럼 보입니다.

그래서이 질문과 같은 복잡한 모델 객체의 이름과 ID 문자열을 만들 수있는 메커니즘이 있습니까? 그렇다면 어떻게 사용됩니까? 그렇지 않다면 폼 데이터를 객체 모델에 다시 바인딩 할 수 있도록 비교적 간단한 이름과 ID 생성 방법이 있습니까?

감사합니다.

답변

3

MVC 프레임 워크 에 적절한 메커니즘이 내장되어있어 적절한 이름과 ID를 생성 할 수 있기를 바랍니다. 그렇지 않으면이 은 반사의 미로처럼 보입니다.

물론 이러한 메커니즘이 있습니다. 내장 된 도우미는 어떻게 생각하십니까? ASP.NET MVC 프레임 워크의 소스 코드를 읽지 않으십니까? 아니면 반사경이나 뭐 사용합니까?

string name = ExpressionHelper.GetExpressionText(forExpression); 
var ti = htmlHelper.ViewContext.ViewData.TemplateInfo; 
string fullHtmlFieldName = ti.GetFullHtmlFieldName(name); 
string id = ti.GetFullHtmlFieldId(fullHtmlFieldName); 
// Now go ahead and use fullHtmlFieldName and id 

var returnText = string.Format(
    "<select id=\"{0}\" name=\"{1}\"", 
    id, 
    fullHtmlFieldName 
); 

아 내가 잊어 버리기 전에 : 같은 대신 제대로 아무것도 인코딩하지 않습니다이 끔찍한 문자열 연결로 <select>으로 DOM 요소를 생성하는 TagBuilder을 사용하십시오. 루프 안의 문자열에 대해서도 += 연산자를 사용하는 것은 아닙니다. 문자열은 변경되지 않으며 메모리 할당이 필요합니다! 적어도 StringBuilder을 사용하십시오.

+0

... 나는 MVC 프레임 워크의 소스 코드를 읽는 것에 대해 농담을하고 있다고 생각합니다. 'TagBuilder'는 내가 조사 할 어떤 것입니다. 그러나 내 방어에서 인코딩해야 할 모든 것이 인코딩됩니다. 선택 상자의 실제 크기 제한을 고려해 볼 때, 나는'+ = '연산이 반드시 큰 문제는 아니지만 그렇다고 더 좋을 수 있다고 생각합니다. –

+4

아니, 물론 나는 소스 코드를 읽는 것에 대해 농담하지 않는다. 나는이 프레임 워크가 어떻게 만들어지고 작동하는지 모른 채 사람들이 어떤 프레임 워크로 고급 어플리케이션을 개발할 수있는 방법을 상상조차 할 수 없다. 나는 당신이 모든 것을 인코딩한다는 것에 동의하지만, 왜 수동으로해야 하는가? 이 측면에서 당신을 도울 프레임 워크에 이미 존재하는 메커니즘이있을 때 바퀴를 다시 발명해야하는 이유는 무엇입니까? –

+0

솔직히 말해서 나는 그와 같은 메커니즘이 있다는 것을 몰랐다. 그것은 질문의 이유이다. 나는 항상 코드를 개선 할 방법을 찾고 있지만, 프레임 워크의 소스 코드를 읽는 것은 다소 어려울 것 같다. –