2010-08-18 9 views
5

Al usar el siguiente código, los id del campo y el id en el atributo for de la etiqueta no son idénticos.LabelFor y TextBoxFor no generan el mismo id.

<%: Html.LabelFor(x => x.Localizations["en"]) %> => Localizations[en] 
<%: Html.TextBoxFor(x=> x.Localizations["en"]) %> => Localizations_en_ 

<%: Html.LabelFor(x => x.Localizations["en"].Property) %> 
     => Localizations[en]_Property 
<%: Html.TextBoxFor(x=> x.Localizations["en"].Property) %> 
     => Localizations_en__Property 

Rastreé el código en el reflector y vi que la forma en que se generan los valores es diferente. No usa el mismo método de ayuda.

LabelFor usa HtmlHelper.GenerateIdFromName y TextBoxFor usa TagBuilder#GenerateId.

¿Alguien sabe el motivo de esto o una solución alternativa (excepto escribir su propio conjunto completo de input/textarea/select helpers)? O se trata de un error?

ACTUALIZACIÓN:

Ya que de todos modos se utiliza un helper HTML para la etiqueta con un segundo parámetro para el texto de la etiqueta, que se modificó por utilizar el mismo código de identificación como la generación de los ayudantes de campo de formulario.

public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, string labelText) 
{ 
    // The main part of this code is taken from the internal code for Html.LabelFor<TModel, TValue>(...). 
    var metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData); 
    var fieldName = ExpressionHelper.GetExpressionText(expression); 

    TagBuilder builder = new TagBuilder("label"); 
    // Generate the id as for the form fields (adds it to self). 
    builder.GenerateId(fieldName); 
    // Use the generated id for the 'for' attribute. 
    builder.Attributes.Add("for", builder.Attributes["id"]); 
    // Remove the id again. 
    builder.Attributes.Remove("id"); 
    builder.SetInnerText(labelText); 
    return MvcHtmlString.Create(builder.ToString()); 
} 

esto resuelve mi problema inmediato, pero no responde a la pregunta de por qué la aplicación se ve como lo hace en MVC2. Si hay una razón para eso

Por cierto: no es necesario modificar realmente el atributo id/for en HTML5, ya que es perfectamente legal tener una identificación que se parezca a ^~[] si lo desea. Todos los principales navegadores lo admiten. Esto está muy bien explicado por Mathias Bynens.

ACTUALIZACIÓN 2:

Esto no resuelve el problema en absoluto en realidad, ya que el DefaultModelBinder no puede unirse a él de todos modos. No parece el uso de objetos anidados en los diccionarios ser apoyado por el generador de nombres de campo en MVC 2, ya que genera:

<input type="text" name="Dict[en]" value="(VALUE)"> 

En lugar de lo que el ligante modelo quiere:

<input type="hidden" name="Dict[0].Key" value="en"> 
<input type="text" name="Dict[0].Value" value="(VALUE)"> 

extraño que sale de la caja de esta manera.

He intentado crear una carpeta de modelo personalizado para ello, pero no puedo conseguir MVC2 usarlo todo lo que trato de usarlo en:

ModelBinders.Binders.Add(typeof(IDictionary<string,object>), new DictionaryModelBinder()); 
ModelBinders.Binders.Add(typeof(IDictionary<string,string>), new DictionaryModelBinder()); 
ModelBinders.Binders.Add(typeof(IDictionary), new DictionaryModelBinder()); 
ModelBinders.Binders.Add(typeof(Dictionary), new DictionaryModelBinder()); 

Así que ahora mismo parece que es hora de volver a crear manualmente los valores de atributo de nombre con los campos ocultos .Key.

+0

he notado lo mismo. aunque nunca uso etiquetas en una estructura repetitiva. Yo uso una mesa ¿Lo intentó en un bucle foreach? ¿Cómo se ve eso? – Stefanvds

+0

De hecho, lo uso en un bucle foreach, este fue un ejemplo simplificado con clave explícita para la legibilidad. –

Respuesta

3

Este es un error en MVC3 que estamos planeando solucionar para la próxima versión (MVC 3 RTM). LabelFor pasará por el constructor de etiquetas para generar el atributo 'para' usando la misma lógica que se usa para generar identificadores, de modo que se alinearán para matrices y tipos anidados.

Actualmente estamos utilizando la especificación html 4.01 para generar identificadores, por lo que no puede usar identificadores que comiencen con letras que no sean letras. Pensaremos cuál debería ser el mejor enfoque ahora que los estándares han cambiado.

+0

Me alegra encontrar que esto está en la lista de cosas para arreglar. Acabo de pasar media hora buscando en Google sin mucho éxito. Muy frustrante. –

Cuestiones relacionadas