Como usar travessões em atributos data-* HTML-5 no ASP.NET MVC

Eu estou tentando usar os atributos de dados HTML5 no meu projeto asp.net MVC 1. (Sou um novato em C # e ASP.NET MVC).

 

Os “detalhes dos dados” nos atributos html acima fornecem o seguinte erro:

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

Ele funciona quando eu uso data_details, mas eu acho que ele precisa começar com “data-” de acordo com a especificação.

Minhas perguntas:

  • Existe alguma maneira de obter este trabalho e usar os atributos de dados HTML5 com Html.ActionLink ou ajudantes Html semelhantes?
  • Existe algum outro mecanismo alternativo para append dados personalizados a um elemento? Esses dados devem ser processados ​​posteriormente pelo JS.

Atualização: MVC 3 e versões mais recentes têm suporte embutido para isso. Veja a resposta altamente votada de JohnnyO abaixo para as soluções recomendadas.

Eu não acho que haja algum ajudante imediato para conseguir isso, mas eu tenho duas idéias para você tentar:

 // 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" ) )%> 

Apenas idéias, não testei isso.

Esse problema foi resolvido no ASP.Net MVC 3. Eles agora convertem automaticamente sublinhados nas propriedades do atributo html em traços. Eles tiveram sorte neste, já que sublinhados não são legais em atributos HTML, então MVC pode confiantemente sugerir que você gostaria de um traço quando você usa um sublinhado.

Por exemplo:

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

vai renderizar isso no MVC 3:

  

Se você ainda estiver usando uma versão mais antiga do MVC, poderá imitar o que o MVC 3 está fazendo criando este método estático que tomei emprestado do código-fonte do 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; } } 

E então você pode usá-lo assim:

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

e isso renderizará o atributo data- * correto:

  

É ainda mais fácil do que tudo sugerido acima. Atributos de dados no MVC que incluem traços (-) são atendidos com o uso de sublinhado (_).

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

Eu vejo JohnnyO já mencionou isso.

Em mvc 4 Poderia ser renderizado com sublinhado (“_”)

Navalha:

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

Renderizado Html

 Vote 

Você pode implementar isso com uma nova function de extensão auxiliar Html, que será usada de forma semelhante aos 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)); } 

E você chama assim …

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

Simples 🙂

editar

pouco mais de escrever aqui

Acabei usando um hyperlink normal junto com Url.Action , como em:

  <%: node.Name %>  

É mais feio, mas você tem um pouco mais de controle sobre a tag a, que às vezes é útil em sites altamente AJAXified.

HTH

Eu não gosto de usar tag “a” pura, muita digitação. Então eu venho com solução. Em vista, parece

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

Implementação da class 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)); } } 

Você pode usá-lo assim:

Em Mvc:

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

Em Html: