Cara menggunakan tanda hubung dalam atribut data-HTML HTML-5 di ASP.NET MVC

325

Saya mencoba menggunakan atribut data HTML5 dalam proyek ASP.NET MVC 1 saya. (Saya seorang pemula C # dan ASP.NET MVC.)

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

"Data-detail" di htmlAttributes di atas memberikan kesalahan berikut:

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

Ini bekerja ketika saya menggunakan data_details, tapi saya kira itu harus dimulai dengan "data-" sesuai spesifikasi.

Pertanyaan saya:

  • Apakah ada cara untuk membuatnya berfungsi dan menggunakan atribut data HTML5 dengan Html.ActionLink atau pembantu Html serupa?
  • Apakah ada mekanisme alternatif lain untuk melampirkan data khusus ke suatu elemen? Data ini akan diproses nanti oleh JS.
Shameem
sumber
5
ini adalah pertanyaan lama dengan jawaban yang sudah ketinggalan zaman - pengguna MVC 3 dan di atasnya harus melihat pertanyaan ini stackoverflow.com/questions/2897733/…
ED-209

Jawaban:

115

Pembaruan: MVC 3 dan versi yang lebih baru memiliki dukungan bawaan untuk ini. Lihat jawaban JohnnyO yang sangat terunggul di bawah ini untuk solusi yang disarankan.

Saya tidak berpikir ada pembantu langsung untuk mencapai ini, tetapi saya punya dua ide untuk Anda coba:

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

Hanya ide, belum mengujinya.

Morten Mertner
sumber
5
Hai. Jika Anda ingin menggunakan pendekatan 1, pastikan kamus Anda bertipe Kamus <String, Object>.
Ondrej Stastny
40
Meskipun ini secara teknis berfungsi, cara yang disarankan (dimulai dengan MVC 3) adalah dengan menggunakan garis bawah sebagai ganti tanda hubung (seperti yang ditunjukkan oleh JohnnyO).
Curtis Buys
3
Membingungkan seluruh dunia dengan jawaban yang dipilih ini sampai memperhatikan jawaban yang sebenarnya di atas!
Rubens Mariuzzo
648

Masalah ini telah diatasi dalam ASP.Net MVC 3. Mereka sekarang secara otomatis mengkonversi garis bawah dalam properti atribut html ke tanda hubung. Mereka beruntung dalam hal ini, karena garis bawah tidak sah dalam atribut html, jadi MVC dapat dengan yakin menyatakan bahwa Anda ingin tanda hubung saat Anda menggunakan garis bawah.

Sebagai contoh:

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

akan membuat ini dalam MVC 3:

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

Jika Anda masih menggunakan versi MVC yang lebih lama, Anda bisa meniru apa yang dilakukan MVC 3 dengan membuat metode statis yang saya pinjam dari kode sumber 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;
    }
}

Dan kemudian Anda dapat menggunakannya seperti ini:

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

dan ini akan membuat atribut data- * yang benar:

<input data-bind="foo" id="City" name="City" type="text" value="" />
Johnny Oshika
sumber
6
Ini tidak berhasil bagi saya karena suatu alasan. Lihat sumber menunjukkan data_ *. Menggunakan MVC3. Ada ide?
Simon Hartcher
Hai Simon, apakah Anda menyelesaikan masalah Anda? Jika tidak, dapatkah Anda memberikan kode yang menyebabkan masalah?
Johnny Oshika
Masih belum berhasil WebGrid.GetHtml(htmlAttributes: new { data_some : "thing" }). : '(
Rubens Mariuzzo
+1 untuk menentukan mengapa garis bawah akan berfungsi. Tidak terpikir oleh saya bahwa garis bawah tidak valid dalam nama atribut untuk HTML!
Umar Farooq Khawaja
2
@ RubensMariuzzo ini tidak dimasukkan ke dalam RouteValueDictionarytetapi ke Html.Something()metode MVC3 . Mungkin saja yang WebGridbelum ditingkatkan dengan cara yang sama, atau Anda dapat memeriksa versi diSystem.Web.Helpers.dll
Keith
58

Ini bahkan lebih mudah dari semua yang disarankan di atas. Atribut data dalam MVC yang mencakup tanda hubung (-) dipenuhi dengan penggunaan garis bawah (_).

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

Saya melihat JohnnyO sudah menyebutkan ini.

Oliver
sumber
12
Metode yang bertanggung jawab untuk ini adalah: HtmlHelper.AnonymousObjectToHtmlAttributes (objek), jika ada yang bertanya-tanya mengapa ekstensi kustom mereka tidak akan mengganti garis bawah dengan tanda hubung.
Nikkelmann
1
Ini benar-benar perlu dipilih karena sejauh ini merupakan jawaban paling sederhana dan berfungsi dengan sempurna!
Dan Diplo
21

Dalam mvc 4 Dapat diterjemahkan dengan Garis Bawah ("_")

Pisau cukur:

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

Html yang Diberikan

<a class="votes" data-fid="18587" data-jid="9" href="/Home/%23/18587">Vote</a>
mzonerz
sumber
hai, apakah ada cara untuk POST data-fid ke controller, melalui Ajax atau kirim. bertanya-tanya bagaimana cara memanfaatkan data. Misalnya, jika saya memiliki data-dateatribut, Bagaimana saya bisa mempostingnya ke controller / action? Juga apa% 23 di sana
transformator
Ya, gunakan pengumpulan formulir dan akses dengan ID atau Nama, dan% 23 adalah #
mzonerz
4

Anda dapat menerapkan ini dengan fungsi ekstensi pembantu HTML yang baru yang kemudian akan digunakan mirip dengan ActionLinks yang ada.

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

Dan Anda menyebutnya seperti itu ...

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

Simples :-)

sunting

sedikit lebih banyak menulis di sini

WestDiscGolf
sumber
3

Saya akhirnya menggunakan hyperlink normal bersama Url.Action, seperti pada:

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

Ini lebih buruk, tetapi Anda memiliki kontrol lebih besar atas atag, yang kadang-kadang berguna di situs AJAXified.

HTH

Keith Williams
sumber
0

Saya tidak suka menggunakan tag "a" murni, terlalu banyak mengetik. Jadi saya datang dengan solusi. Dalam pandangannya terlihat

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

Implementasi kelas 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));
    }
}
msa.im
sumber
1
Tentunya ada nama kelas yang lebih baik ... tambahan tpada akhirnya setidaknya!
hvaughan3
-2

Anda bisa menggunakannya seperti ini:

Dalam Mvc:

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

Dalam Html:

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