วิธีใช้ขีดกลางในแอตทริบิวต์ HTML-5 data- * ใน ASP.NET MVC


325

ฉันกำลังพยายามใช้ข้อมูล 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"   })%>

"data-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

5
นี่เป็นคำถามเก่าที่มีคำตอบที่ล้าสมัย - ผู้ใช้ MVC 3 ขึ้นไปควรดูคำถามนี้stackoverflow.com/questions/2897733//
ED-209

คำตอบ:


115

อัปเดต: 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" ) )%>

แค่ความคิดยังไม่ได้ทดสอบ


5
สวัสดี หากคุณต้องการใช้วิธีที่ 1 ตรวจสอบให้แน่ใจว่าพจนานุกรมของคุณเป็นพจนานุกรมประเภท <String, Object>
Ondrej Stastny

40
ในขณะที่ใช้งานได้ทางเทคนิควิธีที่แนะนำ (เริ่มต้นด้วย MVC 3) คือการใช้เครื่องหมายขีดล่างแทนเครื่องหมายยัติภังค์ (ดังที่ JohnnyO ชี้ให้เห็น)
เคอร์ติสซื้อ

3
ทำให้โลกทั้งโลกสับสนกับคำตอบที่เลือกนี้จนกว่าจะสังเกตเห็นคำตอบที่แท้จริงข้างต้น!
รูเบนส์ Mariuzzo

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 รุ่นที่เก่ากว่าคุณสามารถเลียนแบบสิ่งที่ 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="" />

6
มันใช้งานไม่ได้สำหรับฉันด้วยเหตุผลบางอย่าง แหล่งที่มาดูข้อมูล data_ * ใช้ MVC3 ความคิดใด ๆ
Simon Hartcher

สวัสดี Simon คุณแก้ปัญหาของคุณแล้วหรือยัง? ถ้าไม่คุณสามารถให้รหัสที่เป็นสาเหตุของปัญหาได้หรือไม่
Johnny Oshika

WebGrid.GetHtml(htmlAttributes: new { data_some : "thing" })ยังไม่มีโชคกับ : '(
Rubens Mariuzzo

+1 สำหรับการระบุสาเหตุที่ขีดล่างใช้งานได้ มันไม่ได้เกิดขึ้นกับฉันว่าขีดเส้นใต้ไม่ถูกต้องในชื่อแอตทริบิวต์สำหรับ HTML!
Umar Farooq Khawaja

2
@RubensMariuzzo สิ่งนี้ไม่ได้ถูกอบRouteValueDictionaryเข้าสู่ แต่เข้าสู่Html.Something()วิธีการของ MVC3 เป็นไปได้ที่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

1
นี่ต้องลงคะแนนเพราะมันเป็นคำตอบที่ง่ายที่สุดและทำงานได้อย่างสมบูรณ์แบบ!
Dan Diplo

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>

สวัสดีมีวิธี POST data-fid ไปยังคอนโทรลเลอร์ผ่าน Ajax หรือส่ง สงสัยว่าจะใช้ประโยชน์จากข้อมูลได้อย่างไร เช่นถ้าฉันมีdata-dateในคุณลักษณะฉันจะโพสต์ไปยังตัวควบคุม / การกระทำได้อย่างไร นอกจากนี้% 23 ที่นั่นคืออะไร
หม้อแปลง

ใช่ใช้การรวบรวมแบบฟอร์มและเข้าถึงด้วย ID หรือชื่อและ% 23 คือ #
mzonerz

4

คุณสามารถใช้สิ่งนี้ได้ด้วยฟังก์ชั่นส่วนขยาย Html helper ใหม่ซึ่งจะถูกนำไปใช้ในลักษณะเดียวกับ 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" })  %>

Simples :-)

แก้ไข

เขียนเพิ่มขึ้นอีกนิดที่นี่


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

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