2013-03-17 90 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