Como eu acesso HtmlHelper métodos de dentro de meu próprio HtmlHelper?
-
20-08-2019 - |
Pergunta
Eu estou escrevendo minha própria extenstion HtmlHelper para 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
// .....
};
Onde eu estou tendo problemas é tryin para acesso UrlHelper
de dentro definição do meu HtmlHelper. O problema é que a maneira como você HtmlHelper
normalmente acesso (via Html.MethodName(...)
) é através de uma propriedade na View. Isto não está disponível para mim, obviamente, a partir de minha própria classe de extensão.
Este é o código real MVC fonte para ViewMasterPage
(a partir de Beta) -. Que define Html
e 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; }
}
Eu quero ser capaz de acessar essas propriedades dentro de um HtmlHelper.
O melhor que eu vim acima com é este (inserção no início do método CreateDialogLink
)
HtmlHelper Html = new HtmlHelper(htmlHelper.ViewContext, htmlHelper.ViewDataContainer);
UrlHelper Url = new UrlHelper(htmlHelper.ViewContext.RequestContext);
Estou faltando alguma outra maneira de acessar as instâncias HtmlHelper
e UrlHelper
existentes - ou eu realmente preciso para criar um novo? Tenho certeza de que não há muito em cima, mas eu prefiro usar os pré-existentes se eu puder.
Solução
Antes de fazer esta pergunta que eu tinha olhado para algum do código fonte MVC, mas evidentemente eu perdi isso, que é como eles fazem isso para o ajudante de imagem.
[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);
}
Looks como instanciar um novo UrlHelper
é a abordagem correta depois de tudo. Isso é bom o suficiente para mim.
Update: código RTM de ASP.NET MVC Source Code v1.0 é ligeiramente diferente como apontado nos comentários.
arquivo: 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);
}
Outras dicas
Eu enfrentei um problema semelhante e decidiu que seria mais fácil apenas chamar a UrlHelper na visão e passar a saída para a minha extensão HtmlHelper. No seu caso, seria algo como:
<%= Html.CreateDialogLink( "text", Url.Content( "~/...path.to.content" ) ) %>
Se você quiser acessar os métodos de extensão sobre o existente HtmlHelper que é passado em sua classe, você só deve precisar importar System.Web.Mvc.Html em seu arquivo de código-fonte e você terá acesso a eles (que é onde as classes de extensão são definidas). Se você quer uma UrlHelper, você precisa instanciar que, como o HtmlHelper você está recebendo não tem uma alça para o ViewPage que ele está vindo.
Se você precisa criar um UrlHelper em uma classe de utilitário que você pode fazer o seguinte:
string url = "~ / content / images / foo.jpg";
var urlHelper = new UrlHelper(new RequestContext(
new HttpContextWrapper(HttpContext.Current),
new RouteData()), RouteTable.Routes);
string absoluteUrl = urlHelper.Content(url);
Isso permite que você use roteamento ou '~ expansão' longe de um contexto MVC.
Bem, você sempre pode passar a instância da página para o método de extensão. Eu acho que é uma maneira muito melhor de fazer isso do que criar novas instâncias em seu método.
Você também pode definir este método em uma classe que deriva de MasterPage / ViewMasterPage e depois derivar a página a partir daí. Desta forma, você tem acesso a todas as propriedades da instância e não tem que passá-los ao redor.