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.
Shameem
quelle
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.

Morten Mertner
quelle
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="" />
Johnny Oshika
quelle
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.

Oliver
quelle
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>
mzonerz
quelle
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

WestDiscGolf
quelle
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

Keith Williams
quelle
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));
    }
}
msa.im
quelle
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"/>
Gururaj Nadager
quelle