Como usar traços nos atributos data-* HTML-5 no ASP.NET MVC


325

Estou tentando usar atributos de dados HTML5 no meu projeto ASP.NET MVC 1. (Sou iniciante em C # e ASP.NET MVC.)

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

Os "dados-detalhes" nos htmlAttributes 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.

Funciona quando uso dados_detalhes, mas acho que precisa começar com "dados-" conforme as especificações.

Minhas perguntas:

  • Existe alguma maneira de fazer isso funcionar e usar atributos de dados HTML5 com os auxiliares Html.ActionLink ou Html semelhantes?
  • Existe algum outro mecanismo alternativo para anexar dados personalizados a um elemento? Esses dados devem ser processados ​​posteriormente pelo JS.

5
esta é uma questão de idade com resposta ultrapassada - utilizadores do MVC e 3 acima devem exibir esta questão stackoverflow.com/questions/2897733/...
ED-209

Respostas:


115

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

Não acho que haja ajudantes imediatos para conseguir isso, mas 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<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" ) )%>

Apenas idéias, não testei.


5
Oi. Se você quiser usar a primeira abordagem, verifique se o seu dicionário é do tipo Dictionary <String, Object>.
Ondrej Stastny

40
Enquanto isso tecnicamente funciona, a maneira recomendada (começando com o MVC 3) é usar um sublinhado no lugar do hífen (como JohnnyO apontou).
Curtis Compra

3
Confundindo o mundo inteiro com esta resposta escolhida até perceber a resposta real acima!
Rubens Mariuzzo

648

Esse problema foi solucionado no ASP.Net MVC 3. Agora, eles convertem automaticamente sublinhados nas propriedades de atributo html em traços. Eles tiveram sorte com este, pois os sublinhados não são legais nos atributos html, portanto, o MVC pode sugerir com confiança que você gostaria de um traço ao usar um sublinhado.

Por exemplo:

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

renderizará isso no MVC 3:

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

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 eu emprestei 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:

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

6
Isso não funciona para mim por algum motivo. Exibir fonte mostra dados_ *. Usando MVC3. Alguma ideia?
22611 Simon Simoncher

Olá Simon, você resolveu o seu problema? Caso contrário, você pode fornecer seu código que está causando o problema?
Johnny Oshika

Ainda sem sorte com WebGrid.GetHtml(htmlAttributes: new { data_some : "thing" }). : '(
Rubens Mariuzzo 26/11

+1 para especificar por que os sublinhados funcionariam. Não me ocorreu que sublinhados não eram válidos em nomes de atributo para HTML!
Umar Farooq Khawaja

2
@RubensMariuzzo, isso não está incluído RouteValueDictionarynos Html.Something()métodos do MVC3 . É possível que WebGridnão tenha sido atualizado da mesma forma, ou você pode verificar a versão noSystem.Web.Helpers.dll
Keith

58

É ainda mais fácil do que tudo sugerido acima. Os 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á mencionado isso.


12
O método responsável por isso é: HtmlHelper.AnonymousObjectToHtmlAttributes (object), caso alguém esteja se perguntando por que sua extensão personalizada não substituirá o sublinhado por um hífen.
Nikkelmann

1
Isso realmente precisa ser votado, pois é de longe a resposta mais simples e funciona perfeitamente!
precisa

21

No mvc 4 pode ser renderizado com sublinhado ("_")

Navalha:

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

Html renderizado

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

oi, existe uma maneira de enviar os dados fid para o controlador, através de um Ajax ou enviar. querendo saber como aproveitar os dados. Por exemplo, se eu tivesse um data-dateno atributo, como eu poderia publicá-lo no controlador / ação? Também o que é% 23 lá
transformador

Sim coleção forma de uso e acesso com ID ou nome, e% 23 é #
mzonerz

4

Você pode implementar isso com uma nova função de extensão auxiliar de HTML, que será usada de maneira 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

um pouco mais de escrever aqui


3

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

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

É mais feio, mas você tem um pouco mais de controle sobre a atag, que às vezes é útil em sites fortemente com AJAX.

HTH


0

Eu não gosto de usar a tag "a" pura, digitando demais. 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 classe 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));
    }
}

1
Certamente existe um nome de classe melhor ... tpelo menos um extra no final!
hvaughan3

-2

Você pode usá-lo assim:

No Mvc:

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

Em HTML:

<input type="text" name="Id" data_val_number="10"/>
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.