319 votes

Comment utiliser les attributs data-* de HTML-5 dans ASP.NET MVC

J'essaie d'utiliser Attributs de données HTML5 dans mon projet ASP.NET MVC 1. (Je suis un débutant en C# et ASP.NET MVC).

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

Les "data-details" dans les htmlAttributes ci-dessus donnent l'erreur suivante :

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

Cela fonctionne lorsque j'utilise data_details, mais je suppose que cela doit commencer par "data-" comme le stipule la spécification.

Mes questions :

  • Existe-t-il un moyen de faire fonctionner ce système et d'utiliser les attributs de données HTML5 avec Html.ActionLink ou des aides Html similaires ?
  • Existe-t-il un autre mécanisme permettant de joindre des données personnalisées à un élément ? Ces données doivent être traitées ultérieurement par JS.

643voto

Johnny Oshika Points 15580

Ce problème a été résolu dans ASP.Net MVC 3. Il convertit désormais automatiquement les traits de soulignement en tirets dans les propriétés d'attributs html. Ils ont eu de la chance sur ce point, car les traits de soulignement ne sont pas légaux dans les attributs html, donc MVC peut impliquer en toute confiance que vous souhaitez un tiret lorsque vous utilisez un trait de soulignement.

Par exemple :

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

rendra ceci dans MVC 3 :

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

Si vous utilisez encore une ancienne version de MVC, vous pouvez imiter ce que fait MVC 3 en créant cette méthode statique que j'ai empruntée au code source 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;
    }
}

Et ensuite tu peux l'utiliser comme ça :

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

et cela rendra l'attribut data-* correct :

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

115voto

Morten Mertner Points 5786

Mise à jour : MVC 3 et les versions plus récentes ont un support intégré pour cela. Voir la réponse de JohnnyO ci-dessous pour les solutions recommandées.

Je ne pense pas qu'il existe des aides immédiates pour y parvenir, mais j'ai deux idées à vous proposer :

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

Ce ne sont que des idées, je ne les ai pas testées.

58voto

Oliver Points 2004

C'est encore plus simple que tout ce qui est suggéré ci-dessus. Dans MVC, les attributs de données qui comprennent des tirets (-) sont pris en charge par l'utilisation du trait de soulignement (_).

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

Je vois que JohnnyO l'a déjà mentionné.

4voto

WestDiscGolf Points 3335

Vous pouvez l'implémenter avec une nouvelle fonction d'extension d'aide Html qui sera ensuite utilisée de manière similaire aux ActionLinks existants.

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));
}

Et tu l'appelles comme ça ...

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

C'est simple :-)

modifier

un peu plus d'informations aquí

3voto

Keith Williams Points 1126

J'ai fini par utiliser un hyperlien normal avec Url.Action comme dans :

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

C'est plus moche, mais tu as un peu plus de contrôle sur le a qui est parfois utile dans les sites fortement AJAXifiés.

HTH

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X