Cómo usar guiones en atributos HTML-5 data- * en ASP.NET MVC

Intento utilizar atributos de datos HTML5 en mi proyecto ASP.NET MVC 1. (Soy un novato de C # y ASP.NET MVC).

 

Los “datos-detalles” en los atributos html anteriores dan el siguiente error:

  CS0746: Invalid anonymous type member declarator. Anonymous type members must be declared with a member assignment, simple name or member access. 

Funciona cuando uso data_details, pero supongo que debe comenzar con “data-” según la especificación.

Mis preguntas:

  • ¿Hay alguna manera de hacer que esto funcione y usar atributos de datos HTML5 con Html.ActionLink o con ayudantes Html similares?
  • ¿Hay algún otro mecanismo alternativo para adjuntar datos personalizados a un elemento? Esta información será procesada posteriormente por JS.

Actualización: MVC 3 y versiones más nuevas tienen soporte integrado para esto. Consulte la respuesta altamente votada de JohnnyO a continuación para conocer las soluciones recomendadas.

No creo que haya ayuda inmediata para lograr esto, pero tengo dos ideas para que intentes:

 // 1: pass dictionary instead of anonymous object <%= Html.ActionLink( "back", "Search", new { keyword = Model.Keyword, page = Model.currPage - 1}, new Dictionary { {"class","prev"}, {"data-details","yada"} } )%> // 2: pass custom type decorated with descriptor attributes public class CustomArgs { public CustomArgs( string className, string dataDetails ) { ... } [DisplayName("class")] public string Class { get; set; } [DisplayName("data-details")] public string DataDetails { get; set; } } <%= Html.ActionLink( "back", "Search", new { keyword = Model.Keyword, page = Model.currPage - 1}, new CustomArgs( "prev", "yada" ) )%> 

Solo ideas, no lo he probado.

Este problema se ha abordado en ASP.Net MVC 3. Ahora convierten automáticamente guiones bajos en propiedades de atributos html en guiones. Tuvieron suerte en este caso, ya que los guiones bajos no son legales en los atributos html, por lo que MVC puede implicar con confianza que le gustaría un guión cuando usa un guión bajo.

Por ejemplo:

 @Html.TextBoxFor(vm => vm.City, new { data_bind = "foo" }) 

lo renderizará en MVC 3:

  

Si todavía está utilizando una versión anterior de MVC, puede imitar lo que MVC 3 está haciendo creando este método estático que tomé prestado del código fuente de MVC3:

 public class Foo { public static RouteValueDictionary AnonymousObjectToHtmlAttributes(object htmlAttributes) { RouteValueDictionary result = new RouteValueDictionary(); if (htmlAttributes != null) { foreach (System.ComponentModel.PropertyDescriptor property in System.ComponentModel.TypeDescriptor.GetProperties(htmlAttributes)) { result.Add(property.Name.Replace('_', '-'), property.GetValue(htmlAttributes)); } } return result; } } 

Y luego puedes usarlo así:

 <%: Html.TextBoxFor(vm => vm.City, Foo.AnonymousObjectToHtmlAttributes(new { data_bind = "foo" })) %> 

y esto hará que el atributo data- * sea correcto:

  

Es incluso más fácil que todo lo sugerido anteriormente. Los atributos de datos en MVC que incluyen guiones (-) se atienden con el uso del guión bajo (_).

 <%= Html.ActionLink("« Previous", "Search", new { keyword = Model.Keyword, page = Model.currPage - 1}, new { @class = "prev", data_details = "Some Details" })%> 

Veo que JohnnyO ya mencionó esto.

En mvc 4 se podría representar con Underscore (“_”)

Maquinilla de afeitar:

 @Html.ActionLink("Vote", "#", new { id = item.FileId, }, new { @class = "votes", data_fid = item.FileId, data_jid = item.JudgeID, }) 

Rendered Html

 Vote 

Puede implementar esto con una nueva función de extensión Html helper que luego se usará de manera similar a los ActionLinks existentes.

 public static MvcHtmlString ActionLinkHtml5Data(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes, object htmlDataAttributes) { if (string.IsNullOrEmpty(linkText)) { throw new ArgumentException(string.Empty, "linkText"); } var html = new RouteValueDictionary(htmlAttributes); var data = new RouteValueDictionary(htmlDataAttributes); foreach (var attributes in data) { html.Add(string.Format("data-{0}", attributes.Key), attributes.Value); } return MvcHtmlString.Create(HtmlHelper.GenerateLink(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, null, actionName, controllerName, new RouteValueDictionary(routeValues), html)); } 

Y lo llamas así …

 <%: Html.ActionLinkHtml5Data("link display", "Action", "Controller", new { id = Model.Id }, new { @class="link" }, new { extra = "some extra info" }) %> 

Simples 🙂

editar

poco más de escribir aquí

Terminé usando un hipervínculo normal junto con Url.Action , como en:

  <%: node.Name %>  

Es más feo, pero tienes un poco más de control sobre la etiqueta a, que a veces es útil en sitios fuertemente AJAXified.

HTH

No me gusta usar la etiqueta “a” pura, escribir demasiado. Entonces vengo con la solución. A la vista, mira

 <%: Html.ActionLink(node.Name, "Show", "Browse", Dic.Route("id", node.Id), Dic.New("data-nodeId", node.Id)) %> 

Implementación de clase Dic

 public static class Dic { public static Dictionary New(params object[] attrs) { var res = new Dictionary(); for (var i = 0; i < attrs.Length; i = i + 2) res.Add(attrs[i].ToString(), attrs[i + 1]); return res; } public static RouteValueDictionary Route(params object[] attrs) { return new RouteValueDictionary(Dic.New(attrs)); } } 

Puedes usarlo así:

En Mvc:

 @Html.TextBoxFor(x=>x.Id,new{@data_val_number="10"}); 

En Html: