337

我正在尝试在我的 ASP.NET MVC 1 项目中使用HTML5 数据属性。(我是 C# 和 ASP.NET MVC 新手。)

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

上述 htmlAttributes 中的“数据详细信息”给出以下错误:

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

它在我使用 data_details 时有效,但我想它需要按照规范以“data-”开头。

我的问题:

  • 有没有办法让这个工作和使用 HTML5 数据属性与 Html.ActionLink 或类似的 Html 助手?
  • 是否有任何其他替代机制可以将自定义数据附加到元素?这些数据稍后将由 JS 处理。
4

8 回答 8

663

此问题已在 ASP.Net MVC 3 中得到解决。它们现在自动将 html 属性属性中的下划线转换为破折号。他们很幸运,因为下划线在 html 属性中是不合法的,因此 MVC 可以自信地暗示您在使用下划线时想要破折号。

例如:

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

将在 MVC 3 中呈现:

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

如果您仍在使用旧版本的 MVC,您可以通过创建这个我从 MVC3 的源代码中借用的静态方法来模仿 MVC 3 正在做的事情:

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

然后你可以像这样使用它:

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

这将呈现正确的 data-* 属性:

<input data-bind="foo" id="City" name="City" type="text" value="" />
于 2010-12-23T01:08:26.840 回答
118

更新:MVC 3 和更新版本对此具有内置支持。有关推荐的解决方案,请参阅下面的 JohnnyO 高度赞成的答案。

我认为没有任何直接的帮手可以实现这一目标,但我确实有两个想法供您尝试:

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

只是想法,没有测试过。

于 2010-03-26T01:27:44.980 回答
61

它甚至比上面建议的一切都容易。MVC 中包含破折号 (-) 的数据属性使用下划线 (_) 来处理。

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

我看到 JohnnyO 已经提到了这一点。

于 2012-06-06T08:14:22.830 回答
28

在 mvc 4 中可以用 Underscore("_") 渲染

剃刀:

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

呈现的 HTML

<a class="votes" data-fid="18587" data-jid="9" href="/Home/%23/18587">Vote</a>
于 2016-02-24T09:40:54.110 回答
4

您可以使用新的 Html 辅助扩展函数来实现这一点,然后将类似于现有的 ActionLinks 使用该函数。

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

你这样称呼它......

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

简单的:-)

编辑

在这里多写一点

于 2011-01-12T21:06:00.153 回答
3

我最终使用了一个普通的超链接以及Url.Action,如下所示:

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

它更丑陋,但您对a标签有更多的控制权,这有时在大量 AJAX 化的网站中很有用。

高温高压

于 2010-07-15T18:46:11.553 回答
0

我不喜欢使用纯粹的“a”标签,打字太多。所以我来了解决方案。在看来它看起来

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

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));
    }
}
于 2010-12-11T12:49:36.327 回答
-2

你可以像这样使用它:

在 Mvc 中:

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

在 HTML 中:

<input type="text" name="Id" data_val_number="10"/>
于 2016-01-08T07:07:24.300 回答