Razor bildirim temelli görünümlerinden MVC HtmlHelper uzantılarını kullanma


121

Bir MVC 3 RTM projesi için App_Code klasörümde Razor bildirim temelli bir yardımcısı oluşturmaya çalışıyordum.

Karşılaştığım sorun, ActionLink gibi MVC HtmlHelper uzantılarının mevcut olmamasıydı. Bunun nedeni, derlenen yardımcıların System.Web.WebPages.HelperPagebir Htmlözellikten türetilmesi ve bir özelliği ifşa etmesine rağmen , türünün System.Web.WebPages.HtmlHelperdeğil türünün olmasıdır System.Web.Mvc.HtmlHelper.

Aldığım hata türüne bir örnek:

'System.Web.Mvc.HtmlHelper', 'ActionLink' için bir tanım içermiyor ve 'System.Web.Mvc.HtmlHelper' türünde ilk bağımsız değişkeni kabul eden 'ActionLink' uzantı yöntemi bulunamadı (bir kullanma yönergesi eksik mi? veya bir montaj referansı?)

Tek çözümüm, kendi HelperPage'imi oluşturmak ve Html özelliğini geçersiz kılmaktı:

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

Daha sonra her yardımcının başına şunu yazmam gerekiyor:

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

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

MVC 3'te bu kadar zor mu yoksa yanlış bir şey mi yapıyorum?


4
Url yardımcısına da ihtiyacınız varsa, bu kod satırını HelperPage'e ekleyebilirsiniz: public static UrlHelper Url {get {return new UrlHelper (Html.ViewContext.RequestContext); }}
Marco Staffoli

Yanıtlar:


42

Bu sorunun Marcindcevabına bir göz atın . Yaşadığınız şey, App_Codeklasöre bildirimsel görünümler koymanın bir sınırlamasıdır .

Yardımcılarınızı App_Code'a koymak işe yarar, ancak belirli MVC senaryolarını etkileyen belirli sınırlamalara sahiptir (örneğin: standart MVC Html yardımcılarına erişim yok)


1
Diğer okuyuculara not: Bu cevap kesinlikle doğrudur, ancak Andrew Nurse'un olası bir geçici çözüm için aşağıdaki ek katkısına da göz atın.
Jordan Grey

38

Sayfa yardımcısına erişebilmem için Web Sayfaları yardımcısı için bir uzantı yöntemi oluşturdum.

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

4
Kullanım:@Html.GetPageHelper().ActionLink("actioname")
deerchao

Bu benim için çalışır, ancak ben eklemek zorunda @using System.Web.Mvcve @using System.Web.Mvc.HtmlApp_Code içindeki cshtml yardımcıları dosyasına
Tomino

1
Neden ayrı HtmlHelper sınıfı var? İster App_Code ister Görünümlerde olsun aynı olmalıdır. Destansı yarı uygulanan tasarım başarısız.
Triynko

Burada "global" Razor yardımcılarının nasıl yaratılacağını açıklayan iyi bir iş çıkaran weblogs.asp.net/scottgu/… tarafından referans alınmıştır . Öyleyse, yalnızca HtmlHelperkodlama amacıyla sınıfa ihtiyacınız varsa , bunu yapmanın daha da hızlı bir yolunu buldum Microsoft.Security.Application.Encoder: statik sınıf aracılığıyla :Encoder.HtmlAttributeEncode(value)
Matt Borja

11

Omar burada doğru cevabı buldu, ancak bir şey eklemek istedim (Omar'ın cevabını cevap olarak işaretlemekten çekinmeyin).

Bunun v1'de farkındaydık ve üründe harika bir düzeltme elde edemedik, ancak David Ebbo (ASP.Net ekibinde bir mimar) temelde ilk keşif olan bir Visual Studio Code Generator örneği yayınladı. bunun düzgün çalışmasını sağlamak için aradığımız türden fikirler: http://blogs.msdn.com/b/davidebb/archive/2010/10/27/turn-your-razor-helpers-into-reusable-libraries .aspx

Deneyin ve ne düşündüğünüzü görün! Yorumlarınızı bloguna yazarak David'e bildirin.


2
Razor'un sonraki sürümünde bunu düzeltmeyi planlıyor musunuz? Bunun hala VS 11 Beta'da bir sorun olduğunu fark ettim.
Ömer

9

@Jakes cevabına benzer:

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

}

Kullanımı:

@MvcIntrinsics.Html.Raw("test")

Kaynak: Dino Esposito - Microsoft ASP.NET MVC'yi Programlama


1
Bunun gerekli olması ve bunların App_Code'daki görünümler için temel sınıfın bir parçası olmaması bile saçma.
Triynko

7

Alternatif bir çözüm:

Bunu jilet yardımcısı dosyanızın üstüne ekleyin:

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

o zaman şöyle diyelim:

@HHtml.ActionLink("actionname")

Bu başlangıçta benim için işe yaradı gibi görünüyordu, ancak yardımcıyı tekrar aradığımda 'değer beklenen aralığa düşmüyor' dedim.
d219

3

Benim bu konudaki yaklaşımım, sayfayı bir parametre olarak yardımcı yönteme geçirmektir. Yani sizin örneğinizde şöyle olacaktır:

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

Daha sonra, Razor görünümünüzde ihtiyacınız olan yerde şöyle adlandırın:

@YourHelperFilename.DoSomething(this)

Bunu yapmak , genellikle sahip olduğunuz Htmlveya gibi sayfa özelliklerine Url(ve bunun aracılığıyla HtmlHelperuzantılara) anında erişmenizi sağlar .

Ek bir avantaj olarak (buna ihtiyaç duyuyorsanız), sayfanınki gibi örnek özelliklerine de erişebilirsiniz ViewData.


3

Arama yapanların yararına, sınıf kitaplığının bir parçası olarak MVC görünümleri oluştururken aynı hatayı aldım (bileşenin yeniden kullanımı için). Yukarıda kısmen değinilen çözüm, .cshtml dosyasının en üstüne aşağıdaki using ifadelerini eklemekti:

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

Daha fazla çalışmaya gerek yok.


App_Code altında .cshtml dosyamdaki yardımcılarım Intellisense'de tanınmadı. App_code altındaki .cshtml’imin üstüne @usystem.Web.Mvc.Html eklemek işe yaradı.

Bunu yaptığımda, "Could not load type 'System.Web.WebPages.Instrumentation.InstrumentationService' from assembly 'System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'."gezinirken anlıyorum @using System.Web.Mvc. Herhangi bir fikir?
JoeBrockhaus

Bu benim için hiç fark etmez
mems

0

MVC 3 ile ilgili bazı intellisense sorunları olduğunu biliyorum. Web.config'de ayarlanan ad alanına sahipseniz yardımcıların hala çalışacağını düşünüyorum.

MVC 3 RTM yeniden satıldı Bunu mu yoksa beta sürümünü mü kullanıyorsunuz?


0

ASP.NET MVC bu sorunu VS 2013'te çözmüş gibi görünüyor. Bu gönderiye bakın http://aspnet.uservoice.com/forums/41201-asp-net-mvc/suggestions/3670180-support-helper-extensionmethod-this- htmlhelper-ht


Hayır, hiç de değil. Intellisense, uzantı yöntemlerini almıyor ve VS2013 güncelleme 5'im var @using System.Web.Mvc.Html. App_Code'da cshtml dosyasının en üstünde var , ancak @ Html .... yazmak gibi uzantı yöntemlerinden hiçbirini göstermiyor EditorFor. Bunun 2 ana sürümden sonra ve uygulandığını iddia eden blog gönderilerinden sonra çalışmadığı çok açık. Değil. Aslında, genişletme yöntemleri çalışamaz, çünkü System.Web.WebPages.HtmlHelper sınıfını değil System.Web.WebPages.HelperPage sınıfı tarafından gösterilen sınıfını hedefledikleri için.
Triynko
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.