ASP.NET MVCのHTML-5 data- *属性でダッシュを使用する方法


325

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の「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-」で始める必要があると思います。

私の質問:

  • これを機能させ、Html.ActionLinkまたは同様のHtmlヘルパーでHTML5データ属性を使用する方法はありますか?
  • 要素にカスタムデータを添付する他のメカニズムはありますか?このデータは、JSによって後で処理されます。

5
これは時代遅れの答えと古い質問です- MVC 3のユーザおよび上記のこの質問を見る必要があるstackoverflow.com/questions/2897733/...を
ED-209

回答:


115

更新:MVC 3以降のバージョンには、これに対するサポートが組み込まれています。推奨される解決策については、以下のJohnnyOの非常に賛成の回答を参照してください。

私はこれを達成するための直接の助力者はいないと思いますが、私はあなたが試すための2つのアイデアを持っています:

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

アイデアだけですが、テストしていません。


5
こんにちは。1つ目の方法を使用する場合は、辞書のタイプがDictionary <String、Object>であることを確認してください。
Ondrej Stastny 2010年

40
これは技術的には機能しますが、推奨される方法(MVC 3以降)は、ハイフンの代わりにアンダースコアを使用することです(JohnnyOが指摘したとおり)。
Curtisが

3
上記の実際の答えに気付くまで、この選択された答えで全世界を混乱させてください!
ルーベンスマリウッゾ

648

この問題は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="" />

6
これは、なぜか私にはうまくいきません。ソースを表示すると、data_ *が表示されます。MVC3の使用。何か案は?
Simon Hartcher、2011

こんにちはサイモン、問題を解決しましたか?そうでない場合、問題の原因となっているコードを提供できますか?
ジョニー・

まだ運がありませんWebGrid.GetHtml(htmlAttributes: new { data_some : "thing" })。: '(
ルーベンスマリウッゾ

アンダースコアが機能する理由を指定するための+1。アンダースコアがHTMLの属性名で無効であることは私には起こりませんでした!
Umar Farooq Khawaja 2012年

2
@RubensMariuzzoこれは、RouteValueDictionaryMVC3のHtml.Something()メソッドに組み込まれていません。WebGrid同じ方法でアップグレードされていない可能性があります。または、バージョンを確認することができますSystem.Web.Helpers.dll
Keith

58

上記で提案したすべてのものよりもさらに簡単です。ダッシュ(-)を含むMVCのデータ属性は、アンダースコア(_)を使用して提供されます。

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

私はJohnnyOがすでにこれについて言及したのを見ます。


12
これを担当するメソッドは、HtmlHelper.AnonymousObjectToHtmlAttributes(object)です。カスタム拡張機能がアンダースコアをハイフンに置き換えない理由を誰かが疑問に思っている場合に備えて。
Nikkelmann 2013年

1
これは非常に単純な答えであり、完全に機能するため、本当に投票する必要があります!
Dan Diplo 2013

21

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をPOSTする方法はありますか?データを活用する方法を疑問に思います。たとえばdata-date、属性にaがある場合、それをコントローラー/アクションに投稿するにはどうすればよいですか?また、%23は何
変圧器

はい、フォームコレクションを使用し、IDまたは名前でアクセスします。%2​​3は#
mzonerz

4

これは、既存のActionLinksと同様に使用される新しいHtmlヘルパー拡張関数で実装できます。

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

シンプル:-)

編集する

ここでもう少し書く


3

次のようにUrl.Action、と一緒に通常のハイパーリンクを使用することになりました。

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

見た目は醜いですが、aタグをもう少し制御できます。これは、AJAX化されたサイトで役立つ場合があります。

HTH


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

1
きっともっと良いクラス名があります... t少なくとも最後に余分なものがあります!
hvaughan3 2017年

-2

次のように使用できます。

Mvcの場合:

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

HTMLの場合:

<input type="text" name="Id" data_val_number="10"/>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.