Verwendung von Bindestrichen in HTML-5-Daten- * -Attributen in ASP.NET MVC


325

Ich versuche, HTML5-Datenattribute in meinem ASP.NET MVC 1-Projekt zu verwenden. (Ich bin ein C # - und ASP.NET MVC-Neuling.)

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

Die "Datendetails" in den obigen htmlAttributes geben den folgenden Fehler aus:

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

Es funktioniert, wenn ich data_details verwende, aber ich denke, es muss mit "data-" gemäß der Spezifikation beginnen.

Meine Fragen:

  • Gibt es eine Möglichkeit, dies zum Laufen zu bringen und HTML5-Datenattribute mit Html.ActionLink oder ähnlichen Html-Helfern zu verwenden?
  • Gibt es einen anderen alternativen Mechanismus, um benutzerdefinierte Daten an ein Element anzuhängen? Diese Daten sollen später von JS verarbeitet werden.

5
Dies ist eine alte Frage mit veralteter Antwort - Benutzer von MVC 3 und höher sollten diese Frage anzeigen stackoverflow.com/questions/2897733/…
ED-209

Antworten:


115

Update: MVC 3 und neuere Versionen unterstützen dies bereits. In der hoch bewerteten Antwort von JohnnyO finden Sie empfohlene Lösungen.

Ich glaube nicht, dass es unmittelbare Helfer gibt, um dies zu erreichen, aber ich habe zwei Ideen, die Sie ausprobieren sollten:

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

Nur Ideen, habe es nicht getestet.


5
Hallo. Wenn Sie den ersten Ansatz verwenden möchten, stellen Sie einfach sicher, dass Ihr Wörterbuch vom Typ Dictionary <String, Object> ist.
Ondrej Stastny

40
Während dies technisch funktioniert, wird empfohlen (beginnend mit MVC 3), anstelle des Bindestrichs einen Unterstrich zu verwenden (wie JohnnyO hervorhob).
Curtis kauft

3
Verwirren Sie die ganze Welt mit dieser gewählten Antwort, bis Sie die wahre Antwort oben bemerken!
Rubens Mariuzzo

648

Dieses Problem wurde in ASP.Net MVC 3 behoben. Sie konvertieren jetzt automatisch Unterstriche in HTML-Attributeigenschaften in Bindestriche. Sie hatten Glück, da Unterstriche in HTML-Attributen nicht legal sind, sodass MVC sicher implizieren kann, dass Sie einen Strich möchten, wenn Sie einen Unterstrich verwenden.

Zum Beispiel:

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

wird dies in MVC 3 rendern:

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

Wenn Sie noch eine ältere Version von MVC verwenden, können Sie nachahmen, was MVC 3 tut, indem Sie diese statische Methode erstellen, die ich aus dem Quellcode von MVC3 ausgeliehen habe:

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

Und dann können Sie es so verwenden:

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

und dies wird das richtige Daten- * Attribut rendern:

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

6
Das funktioniert bei mir aus irgendeinem Grund nicht. Quelltext anzeigen zeigt data_ *. Verwenden von MVC3. Irgendwelche Ideen?
Simon Hartcher

Hallo Simon, hast du dein Problem gelöst? Wenn nicht, können Sie Ihren Code angeben, der das Problem verursacht?
Johnny Oshika

Immer noch kein Glück mit WebGrid.GetHtml(htmlAttributes: new { data_some : "thing" }). : '(
Rubens Mariuzzo

+1 für die Angabe, warum Unterstriche funktionieren würden. Mir ist nicht aufgefallen, dass Unterstriche in Attributnamen für HTML nicht gültig sind!
Umar Farooq Khawaja

2
@RubensMariuzzo Dies ist nicht in die, RouteValueDictionarysondern in die MVC3- Html.Something()Methoden eingebrannt . Es ist möglich, dass WebGridnicht auf die gleiche Weise aktualisiert wurde, oder Sie könnten die Version auf derSystem.Web.Helpers.dll
Keith

58

Es ist noch einfacher als alles, was oben vorgeschlagen wurde. Datenattribute in MVC, die Bindestriche (-) enthalten, werden mit dem Unterstrich (_) berücksichtigt.

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

Ich sehe, dass JohnnyO dies bereits erwähnt hat.


12
Die dafür verantwortliche Methode lautet: HtmlHelper.AnonymousObjectToHtmlAttributes (Objekt), falls sich jemand fragt, warum die benutzerdefinierte Erweiterung den Unterstrich nicht durch einen Bindestrich ersetzt.
Nikkelmann

1
Dies muss wirklich abgestimmt werden, da es bei weitem die einfachste Antwort ist und perfekt funktioniert!
Dan Diplo

21

In mvc 4 Könnte mit Unterstrich ("_") gerendert werden

Rasierer:

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

Gerendertes HTML

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

Hallo, gibt es eine Möglichkeit, die Daten-FID über einen Ajax an den Controller zu senden oder zu senden? Ich frage mich, wie ich die Daten nutzen kann. Zum Beispiel, wenn ich ein data-dateAttribut hätte, wie könnte ich es an den Controller / die Aktion senden? Auch was ist% 23 dort
Transformator

Ja, verwenden Sie die Formularsammlung und greifen Sie mit ID oder Name darauf zu.% 23 ist #
mzonerz

4

Sie können dies mit einer neuen HTML-Hilfserweiterungsfunktion implementieren, die dann ähnlich wie die vorhandenen ActionLinks verwendet wird.

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

Und du nennst es so ...

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

Beispiele :-)

bearbeiten

bisschen mehr von einem aufzuschreiben hier


3

Am Ende habe ich einen normalen Hyperlink verwendet Url.Action, wie in:

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

Es ist hässlicher, aber Sie haben etwas mehr Kontrolle über das aTag, was manchmal bei stark AJAXified-Sites nützlich ist.

HTH


0

Ich mag es nicht, reines "a" -Tag zu verwenden, zu viel zu tippen. Also komme ich mit Lösung. In Sicht sieht es aus

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

Implementierung der Dic-Klasse

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
Sicher gibt es einen besseren Klassennamen ... tzumindest am Ende ein Extra !
hvaughan3

-2

Sie können es so verwenden:

In Mvc:

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

In HTML:

<input type="text" name="Id" data_val_number="10"/>
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.