2013-03-17 86 views
0

我使用ASP.NET MVC 2,但是我不認爲我聽說過這個被固定在MVC 3或4,但無論如何:GetFullHtmlFieldId返回不正確的id屬性值

這是我的測試視圖代碼:

<br /> 
<%= Html.LabelFor(m => m.FieldFoo) %> 
<%= Html.TextBoxFor(m => m.FieldFoo) %> 

<br /> 
<%= Html.LabelFor(m => m.CustomFieldValues[0].Value) %> 
<%= Html.TextBoxFor(m => m.CustomFieldValues[0].Value) %> 

而這就是呈現:

<br /> 
<label for="FieldFoo">Foo?</label> 
<input id="FieldFoo" name="FieldFoo" type="text" value="foo" /> 

<br /> 
<label for="CustomFieldValues[0]_Value">Value</label> 
<input id="CustomFieldValues_0__Value" name="CustomFieldValues[0].Value" type="text" value="bar" /> 

現貨的區別:索引屬性CustomFieldValues是不是有其[和對於for=""屬性,將個字符替換爲_。爲什麼?

我踏進LabelFor代碼中看到它調用html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName));而MVC的內部InputHelper具有使用TagBuilder.CreateSanitizedId()這可以解釋爲什麼它變得不同id=""屬性值其自身的邏輯。

MVC 2有沒有解決這個問題的方法?

回答

0

ASP.NET MVC 2沒有帶有HTMLAttributes參數的LabelFor擴展方法。看到這blog post。我們可以創建一個擴展,它將添加此參數並解決您的上述問題。下面是示例,

public static class MyTagBuilder 
{ 
    public static string CreateSanitizedId(string originalId) 
    { 
     return CreateSanitizedId(originalId, HtmlHelper.IdAttributeDotReplacement); 
    } 

    public static string CreateSanitizedId(string originalId, string invalidCharReplacement) 
    { 
     if (String.IsNullOrEmpty(originalId)) 
     { 
      return null; 
     } 

     if (invalidCharReplacement == null) 
     { 
      throw new ArgumentNullException("invalidCharReplacement"); 
     } 

     char firstChar = originalId[0]; 
     if (!Html401IdUtil.IsLetter(firstChar)) 
     { 
      // the first character must be a letter 
      return null; 
     } 

     StringBuilder sb = new StringBuilder(originalId.Length); 
     sb.Append(firstChar); 

     for (int i = 1; i < originalId.Length; i++) 
     { 
      char thisChar = originalId[i]; 
      if (Html401IdUtil.IsValidIdCharacter(thisChar)) 
      { 
       sb.Append(thisChar); 
      } 
      else 
      { 
       sb.Append(invalidCharReplacement); 
      } 
     } 

     return sb.ToString(); 
    } 

    private static class Html401IdUtil 
    { 
     private static bool IsAllowableSpecialCharacter(char c) 
     { 
      switch (c) 
      { 
       case '-': 
       case '_': 
       case ':': 
        // note that we're specifically excluding the '.' character 
        return true; 

       default: 
        return false; 
      } 
     } 

     private static bool IsDigit(char c) 
     { 
      return ('0' <= c && c <= '9'); 
     } 

     public static bool IsLetter(char c) 
     { 
      return (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')); 
     } 

     public static bool IsValidIdCharacter(char c) 
     { 
      return (IsLetter(c) || IsDigit(c) || IsAllowableSpecialCharacter(c)); 
     } 
    } 

} 
public static class LabelExtensions 
{ 
    public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object htmlAttributes) 
    { 
     return LabelFor(html, expression, new RouteValueDictionary(htmlAttributes)); 
    } 
    public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, IDictionary<string, object> htmlAttributes) 
    { 
     ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData); 
     string htmlFieldName = ExpressionHelper.GetExpressionText(expression); 
     string labelText = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last(); 
     if (String.IsNullOrEmpty(labelText)) 
     { 
      return MvcHtmlString.Empty; 
     } 

     TagBuilder tag = new TagBuilder("label"); 
     tag.MergeAttributes(htmlAttributes); 
     tag.Attributes.Add("for", MyTagBuilder.CreateSanitizedId(html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(htmlFieldName))); 
     tag.SetInnerText(labelText); 
     return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal)); 
    } 
} 


<%@ Import Namespace="NameSpaceOfTheExtensionMethodClass" %> 


<%= Html.LabelFor(m => m.CustomFieldValues[0].Value, new { })%> 
<%= Html.TextBoxFor(m => m.CustomFieldValues[0].Value)%> 
+0

爲接受,因爲它是正確的,但在我來說,我使用反射來調用MVC自己正確的ID生成方法,而不是重新實現它自己,我會慶祝你的答案。 – Dai 2013-03-25 08:37:11

+0

@戴,請包括什麼爲你工作。 – xr280xr 2014-09-12 14:52:42