Pregunta

Estoy escribiendo mi propia extensión 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
            // .....
        };

Donde tengo problemas es al intentar acceder UrlHelper de dentro La definición de mi HtmlHelper.El problema es que la forma habitual de acceder HtmlHelper (a través de Html.MethodName(...) ) es a través de una propiedad en la Vista.Obviamente, esto no está disponible para mí desde mi propia clase de extensión.

Este es el código fuente MVC real para ViewMasterPage (a partir de Beta) - que define Html y 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; }
    }

Quiero poder acceder a estas propiedades dentro de un HtmlHelper.

Lo mejor que se me ocurrió es esto (insertar al principio de CreateDialogLink método)

HtmlHelper Html = new HtmlHelper(htmlHelper.ViewContext, htmlHelper.ViewDataContainer);
UrlHelper Url = new UrlHelper(htmlHelper.ViewContext.RequestContext);

¿Me estoy perdiendo alguna otra forma de acceder a la existente? HtmlHelper y UrlHelper instancias, ¿o realmente necesito crear una nueva?Estoy seguro de que no hay muchos gastos generales, pero preferiría usar los preexistentes si puedo.

¿Fue útil?

Solución

Antes de hacer esta pregunta, había visto algunos de los códigos fuente de MVC, pero evidentemente me perdí esto, que es cómo lo hacen para el ayudante de imagen.

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

Parece que crear instancias de un nuevo UrlHelper es el enfoque correcto después de todo. Eso es lo suficientemente bueno para mí.


Actualización: código RTM de ASP.NET MVC v1.0 Código fuente es ligeramente diferente como se señala en los comentarios.

Archivo: 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);
        }

Otros consejos

Me enfrenté a un problema similar y decidí que sería más fácil llamar a UrlHelper en la vista y pasar el resultado a mi extensión HtmlHelper. En su caso, se vería así:

<%= Html.CreateDialogLink( "text", Url.Content( "~/...path.to.content" ) ) %>

Si desea acceder a los métodos de extensión en el HtmlHelper existente que se pasa a su clase, solo debe importar System.Web.Mvc.Html en su archivo de código fuente y obtendrá acceso a ellos (ahí es donde se definen las clases de extensión). Si desea un UrlHelper, deberá crear una instancia ya que el HtmlHelper que está obteniendo no tiene un identificador para la ViewPage de la que proviene.

Si necesita crear un UrlHelper en una clase de utilidad, puede hacer lo siguiente:

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

Esto le permite usar enrutamiento o '~ expansión' lejos de un contexto MVC.

Bueno, siempre puedes pasar la instancia de la página al método de extensión. Creo que es una forma mucho mejor de hacerlo que crear nuevas instancias en su método.

También podría definir este método en una clase que deriva de MasterPage / ViewMasterPage y luego derivar la página a partir de eso. De esta manera, tiene acceso a todas las propiedades de la instancia y no tiene que pasarlas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top