การใช้ส่วนขยาย MVC HtmlHelper จากมุมมองที่เปิดเผยของ Razor


121

ฉันพยายามสร้างตัวช่วยในการประกาศ Razor ในโฟลเดอร์ App_Code ของฉันสำหรับโครงการ MVC 3 RTM

ปัญหาที่ฉันพบคือส่วนขยาย MVC HtmlHelper เช่น ActionLink ไม่พร้อมใช้งาน นี้เป็นเพราะผู้ช่วยรวบรวมมาจากSystem.Web.WebPages.HelperPageและแม้ว่ามันเสี่ยงHtmlคุณสมบัติของชนิดมากกว่าSystem.Web.WebPages.HtmlHelperSystem.Web.Mvc.HtmlHelper

ตัวอย่างข้อผิดพลาดที่ฉันได้รับคือ:

'System.Web.Mvc.HtmlHelper' ไม่มีคำจำกัดความสำหรับ 'ActionLink' และไม่มีวิธีการขยาย 'ActionLink' ที่ยอมรับอาร์กิวเมนต์แรกของประเภท 'System.Web.Mvc.HtmlHelper' (คุณไม่มีคำสั่งโดยใช้ หรือการอ้างอิงการประกอบ?)

ทางออกเดียวของฉันคือสร้าง HelperPage ของตัวเองและแทนที่คุณสมบัติ Html:

using System.Web.WebPages;

public class HelperPage : System.Web.WebPages.HelperPage 
{
    // Workaround - exposes the MVC HtmlHelper instead of the normal helper
    public static new HtmlHelper Html
    {
        get { return ((System.Web.Mvc.WebViewPage) WebPageContext.Current.Page).Html; }
    }
}

จากนั้นฉันต้องเขียนสิ่งต่อไปนี้ที่ด้านบนของผู้ช่วยทุกคน:

@inherits FunnelWeb.Web.App_Code.HelperPage
@using System.Web.Mvc
@using System.Web.Mvc.Html

@helper DoSomething()
{
    @Html.ActionLink("Index", "Home")
}

MVC 3 มันยากขนาดนี้หรือว่าฉันทำอะไรผิด?


4
หากคุณต้องการตัวช่วย Url ด้วยให้เพิ่มบรรทัดของโค้ดนี้ใน HelperPage: public static UrlHelper Url {get {return new UrlHelper (Html.ViewContext.RequestContext); }}
Marco Staffoli

คำตอบ:


42

ลองดูMarcindคำตอบของคำถามนี้ สิ่งที่คุณพบคือข้อ จำกัด ในการใส่มุมมองที่เปิดเผยในApp_Codeโฟลเดอร์

การกำหนดผู้ช่วยของคุณใน App_Code ได้ผล แต่มีข้อ จำกัด บางประการที่ส่งผลกระทบต่อสถานการณ์ MVC บางอย่าง (ตัวอย่างเช่นไม่มีการเข้าถึงตัวช่วย MVC Html มาตรฐาน)


1
หมายเหตุสำหรับผู้อ่านคนอื่น ๆ : คำตอบนี้ถูกต้อง แต่ยังตรวจสอบการมีส่วนร่วมเพิ่มเติมของ Andrew Nurse ด้านล่างสำหรับวิธีแก้ปัญหาที่อาจเกิดขึ้น
Jordan Grey

38

ฉันสร้างวิธีการขยายสำหรับตัวช่วยหน้าเว็บเพื่อให้ฉันสามารถเข้าถึงตัวช่วยเพจได้

public static HtmlHelper GetPageHelper(this System.Web.WebPages.Html.HtmlHelper html)
{
 return ((System.Web.Mvc.WebViewPage) WebPageContext.Current.Page).Html;
}

4
การใช้งาน:@Html.GetPageHelper().ActionLink("actioname")
deerchao

สิ่งนี้ใช้ได้กับฉัน แต่ฉันต้องเพิ่ม@using System.Web.Mvcและ@using System.Web.Mvc.Htmlลงในไฟล์ตัวช่วย cshtml ภายใน App_Code
Tomino

1
เหตุใดจึงมีคลาส HtmlHelper แยกกัน ควรจะเหมือนกันไม่ว่าจะอยู่ใน App_Code หรือ Views การออกแบบที่ใช้งานได้ครึ่งหนึ่งของมหากาพย์ล้มเหลว
Triynko

ได้รับการอ้างถึงที่นี่โดยweblogs.asp.net/scottgu/…ซึ่งทำงานได้ดีในการอธิบายวิธีการสร้างตัวช่วยมีดโกน "ระดับโลก" ดังนั้นหากคุณต้องการHtmlHelperคลาสเพื่อวัตถุประสงค์ในการเข้ารหัสฉันพบวิธีที่เร็วกว่านี้คือผ่านคลาสแบบคงที่Microsoft.Security.Application.Encoderเช่น:Encoder.HtmlAttributeEncode(value)
Matt Borja

11

Omar มีคำตอบที่ถูกต้องที่นี่ แต่ฉันต้องการเพิ่มบางอย่าง (อย่าลังเลที่จะทำเครื่องหมายคำตอบของ Omar เป็นคำตอบ)

เราตระหนักถึงสิ่งนี้ใน v1 และไม่สามารถแก้ไขปัญหาที่ยอดเยี่ยมในผลิตภัณฑ์ได้ แต่ David Ebbo (สถาปนิกในทีม ASP.Net) ได้โพสต์ตัวอย่าง Visual Studio Code Generator ซึ่งโดยพื้นฐานแล้วเป็นการสำรวจครั้งแรกของ ประเภทของแนวคิดที่เรากำลังมองหาเพื่อทำให้มันทำงานได้อย่างถูกต้อง: http://blogs.msdn.com/b/davidebb/archive/2010/10/27/turn-your-razor-helpers-into-reusable-libraries ขอบ

ลองดูสิว่าคุณคิดอย่างไร! แจ้งให้เดวิดทราบหากคุณมีความคิดเห็นโดยโพสต์ในบล็อกของเขา


2
มีแผนที่จะแก้ไขปัญหานี้ใน Razor เวอร์ชันถัดไปหรือไม่? ฉันสังเกตว่าปัญหานี้ยังคงเป็นปัญหาใน VS 11 Beta
Omar

9

คล้ายกับ @Jakes คำตอบ:

public static class MvcIntrinsics {
    public static System.Web.Mvc.HtmlHelper Html {
        get { return ((System.Web.Mvc.WebViewPage)WebPageContext.Current.Page).Html; }
    }

    public static System.Web.Mvc.AjaxHelper Ajax {
        get { return ((System.Web.Mvc.WebViewPage)WebPageContext.Current.Page).Ajax; }
    }

    public static System.Web.Mvc.UrlHelper Url {
        get { return ((System.Web.Mvc.WebViewPage)WebPageContext.Current.Page).Url; }
    }

}

การใช้งาน:

@MvcIntrinsics.Html.Raw("test")

ที่มา: Dino Esposito - การเขียนโปรแกรม Microsoft ASP.NET MVC


1
เป็นเรื่องน่าขันที่สิ่งนี้จำเป็นด้วยซ้ำและสิ่งเหล่านี้ไม่ได้เป็นเพียงส่วนหนึ่งของคลาสพื้นฐานสำหรับมุมมองใน App_Code
Triynko

7

ทางเลือกอื่น:

เพิ่มสิ่งนี้ที่ด้านบนของไฟล์มีดโกนของคุณ:

@functions {
    public static System.Web.Mvc.HtmlHelper<object> HHtml = ((System.Web.Mvc.WebViewPage)WebPageContext.Current.Page).Html;
}

จากนั้นเรียกสิ่งนี้ว่า:

@HHtml.ActionLink("actionname")

ดูเหมือนว่าตอนแรกจะใช้งานได้สำหรับฉัน แต่เมื่อโทรหาผู้ช่วยเหลืออีกครั้งฉันได้รับ 'ค่าไม่อยู่ในช่วงที่คาดไว้'
d219

3

วิธีการของฉันคือเพียงแค่ส่งหน้าเป็นพารามิเตอร์ไปยังวิธีการช่วยเหลือ ดังนั้นในตัวอย่างของคุณมันจะเป็น:

@helper DoSomething(WebViewPage page)
{
    @page.Html.ActionLink("Index", "Home")
}

จากนั้นในมุมมองมีดโกนของคุณที่คุณต้องการให้เรียกสิ่งนี้ว่า:

@YourHelperFilename.DoSomething(this)

การทำเช่นนี้จะช่วยให้คุณเข้าถึงคุณสมบัติของเพจได้ทันทีเช่นHtmlหรือUrlที่คุณมีอยู่ (และผ่านHtmlHelperส่วนขยายนั้น)

ในฐานะที่เป็นประโยชน์เพิ่มเติม (ถ้าคุณต้องการนี้) ViewDataคุณยังได้รับการเข้าถึงคุณสมบัติเช่นเช่นของหน้า


3

เพื่อประโยชน์ของผู้ค้นหาฉันได้รับข้อผิดพลาดเดียวกันนี้เมื่อสร้างมุมมอง MVC เป็นส่วนหนึ่งของไลบรารีคลาส (สำหรับการใช้คอมโพเนนต์ซ้ำ) วิธีแก้ปัญหาที่กล่าวถึงข้างต้นบางส่วนคือการเพิ่มคำสั่งต่อไปนี้โดยใช้คำสั่งที่ด้านบนของไฟล์. cshtml:

@using System.Web.Mvc
@using System.Web.Mvc.Html

ไม่จำเป็นต้องทำงานต่อไป


ตัวช่วยของฉันใน. cshtml ภายใต้ App_Code ไม่รู้จักใน Intellisense การเพิ่ม @ ใช้ System.Web.Mvc.Html ที่ด้านบนของ. cshtml ของฉันภายใต้ App_code ใช้งานได้

เมื่อผมทำเช่นนี้ฉันได้รับเมื่อโฉบ"Could not load type 'System.Web.WebPages.Instrumentation.InstrumentationService' from assembly 'System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'." @using System.Web.Mvcความคิดใด ๆ ?
JoeBrockhaus

ที่ไม่แตกต่างสำหรับฉัน

0

ฉันรู้ว่ามีปัญหา Intellisense กับ MVC 3 ฉันคิดว่าตัวช่วยจะยังคงใช้งานได้หากคุณตั้งค่าเนมสเปซใน web.config

MVC 3 RTM เพิ่งวางจำหน่ายใหม่คุณกำลังใช้สิ่งนี้หรือเบต้า?


0

ดูเหมือนว่า ASP.NET MVC ได้แก้ไขปัญหานี้แล้วใน VS 2013 ดูโพสต์นี้http://aspnet.uservoice.com/forums/41201-asp-net-mvc/suggestions/3670180-support-helper-extensionmethod-this- HtmlHelper-HT


ไม่ไม่เลย Intellisense ไม่ได้ใช้วิธีการขยายและฉันมีการอัปเดต VS2013 5 ฉันมี@using System.Web.Mvc.Htmlที่ด้านบนของไฟล์ cshtml ใน App_Code แต่การเขียน @Html .... ไม่แสดงวิธีการขยายใด ๆ เช่นEditorFor. เป็นเรื่องน่าขันที่สิ่งนี้ใช้ไม่ได้หลังจากเผยแพร่ 2 ครั้งใหญ่และบล็อกโพสต์ที่อ้างว่ามีการใช้งาน มันไม่ใช่. ในความเป็นจริงวิธีการขยายไม่สามารถทำงานได้เนื่องจากกำหนดเป้าหมายไปที่คลาส System.Web.Mvc.HtmlHelper ไม่ใช่คลาส System.WebWebPages.HtmlHelper ซึ่งถูกเปิดเผยโดยคลาส System.WebWebPages.HelperPage
Triynko
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.