.net asp.net-mvc-3 razor razor-declarative-helpers

.net - ¿Por qué la instancia de HtmlHelper es nula en un método Razor declarative @helper?



asp.net-mvc-3 razor-declarative-helpers (6)

Creo que sé lo que está causando el problema ...

La definición del captador de propiedades Html es:

public static HtmlHelper Html { get { WebPage currentWebPage = CurrentPage as WebPage; if (currentWebPage == null) { return null; } return currentWebPage.Html; } }

Establecer un punto de interrupción en mi método de ayuda muestra que CurrentPage no es en realidad una instancia de WebPage , de ahí el valor null .

Aquí está la jerarquía de CurrentPage de CurrentPage (mis nombres de clase ligeramente CurrentPage ):

ASP._Page_Views_mycontroller_View_cshtml My.Site.MyWebViewPage`1 System.Web.Mvc.WebViewPage`1 System.Web.Mvc.WebViewPage System.Web.WebPages.WebPageBase System.Web.WebPages.WebPageRenderingBase System.Web.WebPages.WebPageExecutingBase System.Object

Tenga en cuenta que la clase base de mi vista se ha especificado en Web.config:

<system.web.webPages.razor> <pages pageBaseType="My.Site.MyWebViewPage"> ...

Que se define tanto en forma genérica como no genérica:

public abstract class MyWebViewPage : WebViewPage { ... } public abstract class MyWebViewPage<TModel> : WebViewPage<TModel> { ... }

Entonces, si este problema no ocurre para otros, quizás no estén usando un pageBaseType personalizado.

Tenga en cuenta también que he colocado la declaración @helper en App_Code/Helpers.cshtml con la esperanza de que sea accesible a nivel mundial.

¿Estoy haciendo algo mal, o es esto un error?

EDITAR Gracias a Darin por señalar esto como un problema conocido. Aún así, ¿por qué no se redefine la propiedad Html como:

public static HtmlHelper Html { get { WebPage currentWebPage = CurrentPage as WebPage; if (currentWebPage != null) { return currentWebPage.Html; } WebViewPage currentWebViewPage = CurrentPage as WebViewPage; if (currentWebViewPage != null) { return currentWebViewPage.Html; } return null; } }

Usando MVC 3 RTM NullReferenceException una extraña NullReferenceException :

@helper TestHelperMethod() { var extra = "class=/"foo/""; <div @Html.Raw(extra)></div> }

Resulta que Html (de tipo HtmlHelper ) es null .

Nunca he visto esto antes en una vista normal. Estoy empezando a experimentar con métodos declarativos de ayuda en Razor (hasta ahora parecen un poco limitados) y estoy bastante perplejo por lo que estoy viendo aquí.


Esa es una limitación conocida de esos ayudantes . Una posibilidad es pasarlo como parámetro:

@helper TestHelperMethod(HtmlHelper html) { var extra = "class=/"foo/""; <[email protected](extra)></div> }

Otra posibilidad es escribir el ayudante como un método de extensión:

public static class HtmlExtensions { public static MvcHtmlString TestHelperMethod(this HtmlHelper) { var div = new TagBuilder("div"); div.AddCssClass("foo"); return MvcHtmlString.Create(div.ToString()); } }

y entonces:

@Html.TestHelperMethod()


Sé que no es el punto, pero si solo es Html.Raw(value) que esperaba utilizar al encontrar esta pregunta en Google (como lo era yo) de acuerdo con el código fuente de System.Web.Mvc.dll todo Html.Raw hace es:

public IHtmlString Raw(string calue) { return new HtmlString(value); }

Así que acabo de usar @(new HtmlString(value)) en mi helper, que funciona muy bien.


Simplemente reemplace

@Html.Raw(extra)

con

@(new HtmlString(extra))


Tuve el mismo problema y esta línea de código hizo el truco. No es una solución para usar HtmlHelper, es solo una forma de escribir RAW html en una máquina de afeitar declarativa.

@{CurrentPage.WriteLiteral("html code");}


Utilizando la sugerencia de Drew Noakes , he llegado a una solución alternativa que por el momento funciona, y que puede eliminarse fácilmente una vez que el problema se resuelve en una versión más nueva de MVC (es decir, si no se cambian más elementos que podrían romperlo :) )

El objetivo es poder utilizar un HtmlHelper dentro de un método de ayuda declarativa que vive en un archivo en App_Code sin tener una NullReferenceException. Para resolver esto, incluí en todos los archivos en App_Code lo siguiente:

@using System.Web.Mvc; @functions { private static new HtmlHelper<object> Html { get { return ((WebViewPage)CurrentPage).Html; } } private static UrlHelper Url { get { return ((WebViewPage)CurrentPage).Url; } } }

Esto parece hacer el truco ya que ahora puedo escribir el siguiente ayudante (en el mismo archivo):

@helper PrintAsRaw(string htmlString) { @Html.Raw(htmlString) }

Obviamente, el método auxiliar es solo un ejemplo. Esta solución tiene la desventaja de que las declaraciones de @functions deben ser introducidas en todos los archivos de declaración de ayuda en App_Code, pero evita complicar la llamada al ayudante, ya que puede simplemente escribir en una vista:

@MyAppCodeFile.PrintAsRaw("<p>My paragraph</p>")

Espero que esto ayude...