Как использовать тире в атрибутах data- * HTML-5 в ASP.NET MVC - PullRequest
314 голосов
/ 26 марта 2010

Я пытаюсь использовать атрибуты данных HTML5 в моем проекте ASP.NET MVC 1. (Я новичок в C # и ASP.NET MVC.)

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

«Данные-данные» в приведенных выше атрибутах html дают следующую ошибку:

 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.

Ответы [ 8 ]

628 голосов
/ 23 декабря 2010

Эта проблема была решена в 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, вы можете имитировать, что делает MVC 3, создав этот статический метод, который я позаимствовал из исходного кода MVC3:

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="" />
114 голосов
/ 26 марта 2010

Обновление: 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" ) )%>

Просто идеи, не проверял.

58 голосов
/ 06 июня 2012

Это даже проще, чем все предложенное выше. Атрибуты данных в MVC, которые включают тире (-), обрабатываются с использованием подчеркивания (_).

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

Я вижу, Джонни уже упоминал об этом.

18 голосов
/ 24 февраля 2016

В MVC 4 Может быть визуализировано с Underscore ("_")

Razor:

@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>
4 голосов
/ 13 января 2011

Это можно реализовать с помощью новой вспомогательной функции расширения Html, которая затем будет использоваться аналогично существующим ссылкам ActionLink.

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

Простые: -)

1010 * редактировать *

немного больше написания здесь

3 голосов
/ 15 июля 2010

Я использовал обычную гиперссылку вместе с Url.Action, как в:

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

Это ужаснее, но у вас есть немного больший контроль над тегом a, который иногда полезен на сайтах с высокой степенью AJAXified.

НТН

0 голосов
/ 08 января 2016

Вы можете использовать это так:

В Mvc:

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

В HTML:

<input type="text" name="Id" data_val_number="10"/>
0 голосов
/ 11 декабря 2010

Мне не нравится использовать чистый тег "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));
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...