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.

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top