wake-up-neo.com

Verwendung von Bindestrichen in HTML-5-Datenattributen in ASP.NET MVC

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 "data-details" 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-Hilfsprogrammen 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.
314
Shameem

pdate: MVC 3 und neuere Versionen unterstützen dies bereits. Empfohlene Lösungen finden Sie in der hoch gelobten Antwort von JohnnyO weiter unten.

Ich denke, es gibt keine unmittelbaren Helfer, 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.

114
Morten Mertner

Dieses Problem wurde in ASP.Net MVC 3 behoben. Sie konvertieren jetzt automatisch Unterstriche in HTML-Attributeigenschaften in Bindestriche. In dieser Hinsicht hatten sie Glück, da Unterstriche in HTML-Attributen nicht zulässig sind. MVC kann also mit Zuversicht andeuten, dass Sie einen Gedankenstrich wünschen, 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 die Funktionsweise von MVC 3 nachahmen, indem Sie diese statische Methode erstellen, die ich aus dem MVC3-Quellcode 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 kannst du es so benutzen:

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

und dies ergibt das richtige data- * Attribut:

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

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, JohnnyO hat das bereits erwähnt.

58
Oliver

In MVC 4 könnte mit Unterstrich ("_") gerendert werden

Rasiermesser:

@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>
18
mzonerz

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

Simples :-)

edit

ein bisschen mehr schreiben hier

4
WestDiscGolf

Am Ende habe ich einen normalen Hyperlink zusammen mit Url.Action Verwendet, 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 Tag a, was manchmal bei stark AJAXified-Websites nützlich ist.

HTH

3
Keith Williams

Ich mag es nicht, ein reines "a" -Tag zu verwenden, zu viel tippen. Also komme ich mit Lösung. Im Blick 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));
    }
}
0
msa7