Как мне получить доступ к методам HtmlHelper из МОЕГО СОБСТВЕННОГО HtmlHelper?
-
20-08-2019 - |
Вопрос
Я пишу свое собственное расширение HtmlHelper для ASP.NET MVC:
public static string CreateDialogLink (this HtmlHelper htmlHelper, string linkText,
string contentPath)
{
// fix up content path if the user supplied a path beginning with '~'
contentPath = Url.Content(contentPath); // doesn't work (see below for why)
// create the link and return it
// .....
};
Где у меня возникают проблемы, так это при попытке получить доступ UrlHelper
От внутри определение моего HtmlHelper.Проблема в том, что способ, которым вы обычно получаете доступ HtmlHelper
(через Html.MethodName(...)
) осуществляется через свойство в представлении.Очевидно, что это недоступно для меня из моего собственного класса расширения.
Это фактический исходный код MVC для ViewMasterPage
(по состоянию на бета-версию) - который определяет Html
и Url
.
public class ViewMasterPage : MasterPage
{
public ViewMasterPage();
public AjaxHelper Ajax { get; }
public HtmlHelper Html { get; }
public object Model { get; }
public TempDataDictionary TempData { get; }
public UrlHelper Url { get; }
public ViewContext ViewContext { get; }
public ViewDataDictionary ViewData { get; }
public HtmlTextWriter Writer { get; }
}
Я хочу иметь возможность доступа к этим свойствам внутри HtmlHelper.
Лучшее, что я придумал, это это (вставить в начале CreateDialogLink
способ)
HtmlHelper Html = new HtmlHelper(htmlHelper.ViewContext, htmlHelper.ViewDataContainer);
UrlHelper Url = new UrlHelper(htmlHelper.ViewContext.RequestContext);
Мне не хватает какого-то другого способа получить доступ к существующему HtmlHelper
и UrlHelper
экземпляры - или мне действительно нужно создать новый?Я уверен, что накладных расходов не так уж много, но я бы предпочел использовать уже существующие, если смогу.
Решение
Прежде чем задать этот вопрос, я просмотрел часть исходного кода MVC, но, очевидно, я пропустил это, как они делают это для Image helper .
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "1#", Justification = "The return value is not a regular URL since it may contain ~/ ASP.NET-specific characters")]
public static string Image(this HtmlHelper helper, string imageRelativeUrl, string alt, IDictionary<string, object> htmlAttributes) {
if (String.IsNullOrEmpty(imageRelativeUrl)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "imageRelativeUrl");
}
UrlHelper url = new UrlHelper(helper.ViewContext);
string imageUrl = url.Content(imageRelativeUrl);
return Image(imageUrl, alt, htmlAttributes).ToString(TagRenderMode.SelfClosing);
}
Похоже на создание экземпляра нового UrlHelper
в конце концов, это правильный подход.Для меня этого достаточно.
Обновить: RTM - код из ASP.NET Исходный код MVC версии v1.0 немного отличается, как указано в комментариях.
Файл:MVC\src\MvcFutures\Mvc\ImageExtensions.cs
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "1#", Justification = "The return value is not a regular URL since it may contain ~/ ASP.NET-specific characters")]
public static string Image(this HtmlHelper helper, string imageRelativeUrl, string alt, IDictionary<string, object> htmlAttributes) {
if (String.IsNullOrEmpty(imageRelativeUrl)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "imageRelativeUrl");
}
UrlHelper url = new UrlHelper(helper.ViewContext.RequestContext);
string imageUrl = url.Content(imageRelativeUrl);
return Image(imageUrl, alt, htmlAttributes).ToString(TagRenderMode.SelfClosing);
}
Другие советы
Я столкнулся с аналогичной проблемой и решил, что было бы проще просто вызвать UrlHelper в представлении и передать выходные данные в мое расширение HtmlHelper.В вашем случае это выглядело бы как:
<%= Html.CreateDialogLink( "text", Url.Content( "~/...path.to.content" ) ) %>
Если вы хотите получить доступ к методам расширения в существующем HtmlHelper, который передается в ваш класс, вам нужно будет только импортировать System.Web.Mvc.Html в вашем файле исходного кода, и вы получите к ним доступ (именно там определены классы расширений).Если вам нужен UrlHelper, вам нужно создать его экземпляр, поскольку у получаемого вами HtmlHelper нет дескриптора для ViewPage, с которой он поступает.
Если вам нужно создать UrlHelper в служебном классе, вы можете сделать следующее :
url-адрес строки = "~/content/images/foo.jpg";
var urlHelper = new UrlHelper(new RequestContext(
new HttpContextWrapper(HttpContext.Current),
new RouteData()), RouteTable.Routes);
string absoluteUrl = urlHelper.Content(url);
Это позволяет вам использовать маршрутизацию или '~ expansion' вдали от контекста MVC.
Что ж, вы всегда можете передать экземпляр страницы методу расширения.Я думаю, что это гораздо лучший способ сделать это, чем создавать новые экземпляры в вашем методе.
Вы также могли бы определить этот метод в классе, который является производным от MasterPage / ViewMasterPage, а затем вывести страницу из этого.Таким образом, у вас есть доступ ко всем свойствам экземпляра, и вам не нужно передавать их по кругу.