asp.net-mvc html5 custom-data-attribute

Cómo utilizar guiones en atributos de datos*HTML-5 en ASP.NET MVC



asp.net-mvc html5 (8)

En mvc 4 se podría representar con un guión bajo ("_")

Maquinilla de afeitar:

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

HTML procesado

<a class="votes" data-fid="18587" data-jid="9" href="/Home/%23/18587">Vote</a>

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

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

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 ayudantes Html similares?
  • ¿Hay algún otro mecanismo alternativo para adjuntar datos personalizados a un elemento? Estos datos serán procesados ​​más tarde por JS.

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 de 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.


Este problema se ha abordado en ASP.Net MVC 3. Ahora convierten automáticamente los guiones bajos en propiedades de atributos html en guiones. Tuvieron suerte con este, 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" })

renderizará esto en MVC 3:

<input data-bind="foo" id="City" name="City" type="text" value="" />

Si aún usas una versión anterior de MVC, puedes 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 representará el atributo data- * correcto:

<input data-bind="foo" id="City" name="City" type="text" value="" />


No me gusta usar la etiqueta "a" pura, demasiado escribir. Así que vengo con la solución. A la vista se ve

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

Implementacion de clase dic.

public static class Dic { public static Dictionary<string, object> New(params object[] attrs) { var res = new Dictionary<string, object>(); 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 implementar esto con una nueva función de extensión de ayuda Html 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

un poco más de una escritura here


Puedes usarlo así:

En Mvc:

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

En HTML:

<input type="text" name="Id" data_val_number="10"/>


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

<a href=''<%= Url.Action("Show", new { controller = "Browse", id = node.Id }) %>'' data-nodeId=''<%= node.Id %>''> <%: node.Name %> </a>

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


Actualización: MVC 3 y las versiones más recientes tienen soporte incorporado para esto. Vea la respuesta altamente actualizada de JohnnyO a continuación para obtener las soluciones recomendadas.

No creo que haya ayudantes inmediatos para lograr esto, pero tengo dos ideas para que pruebes:

// 1: pass dictionary instead of anonymous object <%= Html.ActionLink( "back", "Search", new { keyword = Model.Keyword, page = Model.currPage - 1}, new Dictionary<string,Object> { {"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.