Come utilizzare i trattini negli attributi dati-* HTML-5 in ASP.NET MVC


325

Sto cercando di utilizzare gli attributi di dati HTML5 nel mio progetto ASP.NET MVC 1. (Sono un novizio C # e ASP.NET MVC.)

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

I "dettagli-dati" nel precedente htmlAttributes danno il seguente errore:

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

Funziona quando uso data_details, ma immagino che debba iniziare con "data-" come da specifica.

Le mie domande:

  • Esiste un modo per farlo funzionare e utilizzare gli attributi dei dati HTML5 con Html.ActionLink o simili helper HTML?
  • Esiste un altro meccanismo alternativo per collegare dati personalizzati a un elemento? Questi dati devono essere elaborati in seguito da JS.

5
questa è una vecchia domanda con risposta obsoleta - gli utenti di MVC 3 e versioni successive devono visualizzare questa domanda stackoverflow.com/questions/2897733/…
ED-209

Risposte:


115

Aggiornamento: MVC 3 e le versioni più recenti hanno il supporto integrato per questo. Vedi la risposta altamente votata di JohnnyO di seguito per le soluzioni consigliate.

Non credo che ci siano aiuti immediati per raggiungere questo obiettivo, ma ho due idee da provare:

// 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 idee, non l'ho provato.


5
Ciao. Se vuoi usare il primo approccio, assicurati solo che il tuo dizionario sia di tipo Dizionario <String, Object>.
Ondrej Stastny,

40
Mentre questo funziona tecnicamente, il modo consigliato (a partire da MVC 3) è usare un trattino basso al posto del trattino (come ha sottolineato JohnnyO).
Curtis acquista il

3
Confondere il mondo intero con questa risposta scelta fino a notare la vera risposta sopra!
Rubens Mariuzzo,

648

Questo problema è stato risolto in ASP.Net MVC 3. Ora convertono automaticamente i trattini bassi nelle proprietà dell'attributo html in trattini. Sono stati fortunati su questo, poiché i trattini bassi non sono legali negli attributi html, quindi MVC può implicare con sicurezza che ti piacerebbe un trattino quando usi un trattino basso.

Per esempio:

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

renderà questo in MVC 3:

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

Se stai ancora utilizzando una versione precedente di MVC, puoi imitare ciò che MVC 3 sta facendo creando questo metodo statico che ho preso in prestito dal codice sorgente di 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 quindi puoi usarlo in questo modo:

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

e questo renderà l'attributo data- * corretto:

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

6
Questo non funziona per me per qualche motivo. Visualizza sorgente mostra data_ *. Utilizzando MVC3. Qualche idea?
Simon Hartcher,

Ciao Simone, hai risolto il tuo problema? In caso contrario, puoi fornire il codice che ti sta causando il problema?
Johnny Oshika,

Ancora niente fortuna con WebGrid.GetHtml(htmlAttributes: new { data_some : "thing" }). : '(
Rubens Mariuzzo,

+1 per specificare perché i caratteri di sottolineatura dovrebbero funzionare. Non mi è venuto in mente che i caratteri di sottolineatura non fossero validi nei nomi degli attributi per HTML!
Umar Farooq Khawaja,

2
@RubensMariuzzo questo non è RouteValueDictionaryinserito nel ma nei Html.Something()metodi di MVC3 . È possibile che WebGridnon sia stato aggiornato allo stesso modo, oppure è possibile controllare la versione suSystem.Web.Helpers.dll
Keith

58

È persino più facile di tutto ciò che è stato suggerito sopra. Gli attributi di dati in MVC che includono trattini (-) sono soddisfatti con l'uso del trattino basso (_).

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

Vedo che JohnnyO l'ha già menzionato.


12
Il metodo responsabile per questo è: HtmlHelper.AnonymousObjectToHtmlAttributes (oggetto), nel caso qualcuno si chieda perché la sua estensione personalizzata non sostituirà il trattino basso con un trattino.
Nikkelmann,

1
Questo ha davvero bisogno di essere votato perché è di gran lunga la risposta più semplice e funziona perfettamente!
Dan Diplo,

21

In mvc 4 potrebbe essere eseguito il rendering con Underscore ("_")

Rasoio:

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

HTML reso

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

ciao, c'è un modo per inviare i dati al controller, tramite un Ajax o inviare. chiedendosi come sfruttare i dati. Ad esempio, se avessi un data-dateattributo in, Come potrei pubblicarlo sul controller / azione? Anche ciò che è% 23 lì
trasformatore

Sì, utilizzare la raccolta moduli e accedervi con ID o nome e% 23 è #
mzonerz

4

È possibile implementarlo con una nuova funzione di estensione dell'helper HTML che verrà quindi utilizzata in modo simile ai ActionLink esistenti.

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 lo chiami così ...

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

Semplici :-)

modificare

un po 'più di una scrittura qui


3

Ho finito per usare un normale collegamento ipertestuale insieme a Url.Action, come in:

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

È più brutto, ma hai un po 'più controllo sul atag, che a volte è utile in siti fortemente AJAXified.

HTH


0

Non mi piace usare puro "a" tag, troppa digitazione. Quindi vengo con una soluzione. In vista sembra

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

Implementazione della 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
Sicuramente c'è un nome di classe migliore ... talmeno un extra alla fine!
hvaughan3,

-2

Puoi usarlo in questo modo:

In mvc:

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

In HTML:

<input type="text" name="Id" data_val_number="10"/>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.