如何在 ASP.NET MVC 中的 HTML-5 data-* 属性中使用破折号

Posted

技术标签:

【中文标题】如何在 ASP.NET MVC 中的 HTML-5 data-* 属性中使用破折号【英文标题】:How to use dashes in HTML-5 data-* attributes in ASP.NET MVC 【发布时间】:2011-02-01 00:08:12 【问题描述】:

我正在尝试在我的 ASP.NET MVC 1 项目中使用 html5 data- attributes。 (我是 C# 和 ASP.NET MVC 新手。)

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

上述 htmlAttributes 中的“data-details”给出以下错误:

 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 处理。

【问题讨论】:

这是一个老问题,答案已过时 - MVC 3 及更高版本的用户应查看此问题***.com/questions/2897733/… 【参考方案1】:

此问题已在 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="" />

【讨论】:

由于某种原因这对我不起作用。查看源代码显示 data_*。使用 MVC3。有什么想法吗? 嗨西蒙,你的问题解决了吗?如果没有,您能否提供导致问题的代码? WebGrid.GetHtml(htmlAttributes: new data_some : "thing" ) 仍然没有运气。 :'( +1 用于指定为什么下划线会起作用。我没有想到下划线在 HTML 的属性名称中无效! @RubensMariuzzo 这并没有融入RouteValueDictionary,而是融入了MVC3的Html.Something()方法。可能WebGrid没有升级相同的方式,或者你可以在System.Web.Helpers.dll上查看版本【参考方案2】:

更新: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" ) )%>

只是想法,没有测试过。

【讨论】:

嗨。如果您想使用第一种方法,只需确保您的字典是 Dictionary. 类型 虽然这在技术上可行,但推荐的方法(从 MVC 3 开始)是使用下划线代替连字符(正如 JohnnyO 指出的那样)。 用这个选择的答案让全世界感到困惑直到注意到上面的真实答案!【参考方案3】:

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

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

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

【讨论】:

负责这个的方法是:HtmlHelper.AnonymousObjectToHtmlAttributes(object),以防有人想知道为什么他们的自定义扩展不会用连字符替换下划线。 这确实需要投票,因为它是迄今为止最简单的答案并且效果很好!【参考方案4】:

在 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>

【讨论】:

嗨,有没有办法通过 Ajax 或提交将 data-fid 发布到控制器。想知道如何利用数据。例如,如果我在属性中有 data-date,我如何将其发布到控制器/动作?还有 %23 是什么 是的,使用表单集合并使用 ID 或名称访问它,%23 是#【参考方案5】:

您可以使用新的 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" )  %>

简单:-)

编辑

多写一点here

【讨论】:

【参考方案6】:

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

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

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

HTH

【讨论】:

【参考方案7】:

我不喜欢使用纯粹的“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));
    

【讨论】:

肯定有更好的类名...至少在末尾多了一个t【参考方案8】:

你可以这样使用它:

在 Mvc 中:

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

在 HTML 中:

<input type="text" name="Id" data_val_number="10"/>

【讨论】:

以上是关于如何在 ASP.NET MVC 中的 HTML-5 data-* 属性中使用破折号的主要内容,如果未能解决你的问题,请参考以下文章

在 ASP .NET MVC 5.1/HTML 5 特定中显示日期时间选择器而不是日期选择器

ASP.NET中的MVC如何使用?

如何从 ASP.NET 核心 mvc 向 asp.net 核心中的 Web API 发出 PUT 请求?

ASP.NET MVC 4(测试版)中 HTML-5 data-* 属性的使用是不是中断?

ASP.Net MVC:如何显示模型中的字节数组图像

如何在 ASP.NET MVC 中的 URL 之后允许额外的文本?