Использование расширений MVC HtmlHelper из декларативных представлений Razor
Я пытался создать декларативный помощник Razor в папке App_Code для проекта RTM MVC 3.
Проблема, с которой я столкнулся, заключалась в том, что расширения MVC HtmlHelper, такие как ActionLink, недоступны. Это связано с тем, что скомпилированные помощники происходят из System.Web.WebPages.HelperPage
, и хотя он предоставляет свойство Html
, его тип System.Web.WebPages.HtmlHelper
, а не System.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, или я делаю что-то неправильно?
Ответы
Ответ 1
Посмотрите Marcind
ответ на этот вопрос. То, что вы испытываете, - это ограничение размещения декларативных представлений в папке App_Code
.
Использование ваших помощников в App_Code но имеет определенные ограничения, которые влияют на некоторые сценарии MVC (для пример: нет доступа к стандартному MVC Html. хелперов)
Ответ 2
Я создал метод расширения для помощника WebPages, чтобы получить доступ к помощнику страницы.
public static HtmlHelper GetPageHelper(this System.Web.WebPages.Html.HtmlHelper html)
{
return ((System.Web.Mvc.WebViewPage) WebPageContext.Current.Page).Html;
}
Ответ 3
Омар получил правильный ответ здесь, но я хотел что-то добавить (не стесняйтесь отмечать ответ Омара как ответ).
Мы знали об этом в версии v1 и не смогли получить отличное исправление в продукте, но Дэвид Эббо (архитектор в команде ASP.Net) разместил образец генератора кода Visual Studio, который в основном представляет собой первое исследование тех идей, которые мы рассматриваем, чтобы сделать эту работу должным образом: http://blogs.msdn.com/b/davidebb/archive/2010/10/27/turn-your-razor-helpers-into-reusable-libraries.aspx
Попробуй это и посмотри, что ты думаешь! Пусть Давид узнает, есть ли у вас комментарии, разместив в своем блоге.
Ответ 4
Подобно @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
Ответ 5
Альтернативное решение:
Добавьте это поверх своего файла-бритвы-хелпера:
@functions {
public static System.Web.Mvc.HtmlHelper<object> HHtml = ((System.Web.Mvc.WebViewPage)WebPageContext.Current.Page).Html;
}
затем назовите его следующим образом:
@HHtml.ActionLink("actionname")
Ответ 6
В интересах поисковиков я получил ту же ошибку при создании представлений MVC как части библиотеки классов (для повторного использования компонентов). Решение, частично упомянутое выше, состояло в том, чтобы добавить следующие операторы, расположенные в верхней части файла .cshtml:
@using System.Web.Mvc
@using System.Web.Mvc.Html
Нет необходимости в дальнейшей работе.
Ответ 7
Мой подход к этому - просто передать страницу в качестве параметра вспомогательному методу. Поэтому в вашем примере это будет:
@helper DoSomething(WebViewPage page)
{
@page.Html.ActionLink("Index", "Home")
}
Затем в вашем представлении Razor, где вам это нужно, назовите его следующим образом:
@YourHelperFilename.DoSomething(this)
Выполнение этого немедленно дает вам доступ к свойствам страницы, таким как Html
или Url
, которые вы обычно используете (и через это расширения HtmlHelper
).
В качестве дополнительного преимущества (если вам это требуется), вы также получите доступ к свойствам экземпляра, таким как страница ViewData
.
Ответ 8
Я знаю, что с MVC 3 возникают проблемы с intellisense. Я думаю, что помощники будут работать, если у вас есть пространство имен, заданное в web.config.
MVC 3 RTM только что была обновлена, вы используете эту или бета-версию?
Ответ 9
Похоже, что ASP.NET MVC исправил эту проблему в VS 2013. См. этот пост http://aspnet.uservoice.com/forums/41201-asp-net-mvc/suggestions/3670180-support-helper-extensionmethod-this-htmlhelper-ht