Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

17 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
martes, 26 de junio de 2018
ASP.NET Core Con ASP.NET MVC 5 y anteriores solíamos utilizar @helper para crear porciones de HTML reutilizables en el interior de nuestras vistas, tanto para conseguir un código más limpio como para abrazar el principio DRY (Don’t Repeat Yourself), tan frecuentemente apaleado en la capa de presentación.

Recordaréis que esta directiva permitía crear “funciones” en cuyo interior podíamos escribir código Razor (mezclando marcado y C#) que podía ser invocado desde distintos puntos:
@* File: Test.cshtml *|

@Multiplication(2)
@Multiplication(3)

@helper Multiplication(int x)
{
    <h2>Multiplication table of @x</h2>
    <ul>
        @for (var i = 1; i <= 10; i++)
        {
            <li>@x * @i = @(x * i)</li>
        }
    </ul>
}
Además de definirlos y consumirlos desde la misma vista, también era posible crear helpers globales introduciéndolos en App_Code, aunque esta opción me gustaba menos y creo que no la utilicé jamás en aplicaciones reales.
Pues bien, por algunas extrañas razones, en ASP.NET Core la directiva @helper no está disponible, lo que puede complicarnos un poco a la hora de portar vistas antiguas o, simplemente, cuando queramos usarla para mejorar la legibilidad de nuestro código.

¿Podemos conseguir algo similar en ASP.NET Core?

En realidad, en ASP.NET Core existen muchas fórmulas para reutilizar código de marcado; es relativamente sencillo crear HTML helpers, view components, tag helpers o vistas parciales, que nos permitirían conseguirlo. Sin embargo, en mi opinión, ninguna de estas opciones ofrece una solución en determinados escenarios tan elegante, eficiente y fácil de escribir como @helper.

Pero bueno, ciertamente existe una forma que, aunque no con la misma limpieza, al menos nos permite acercarnos un poco a nuestra añorada directiva ;)

El truco consiste en crear un delegado en forma de función lambda Func<T, IHtmlContent>, cuyo cuerpo podemos expresar utilizando sintaxis Razor, como en el siguiente ejemplo:
@* File: Test.cshtml *|
@{
    Func<int, IHtmlContent> Multiplication = @<text>
        <h2>Multiplication table of @item</h2>
        <ul>
            @for (var i = 1; i <= 10; i++)
            {
                <li>@item * @i = @( item * i)</li>
            }
        </ul>
    </text>;
}

@Multiplication(2)
@Multiplication(3)
Pero ojo, que aunque a priori pueda parecer bastante similar a @helper, encontraremos varios inconvenientes:
  • Primero, que al tratarse de una definición inline, sólo puede ser utilizada después de haber sido definida. En la práctica, quiere decir que debemos implementar estas funciones muy al principio de la vista para que estén disponibles en ella.
     
  • Su definición y uso es estrictamente local al archivo actual, es decir, no podemos crearla en _ViewImports.cshtml o en _ViewStart.cshtml y esperar que esté disponible en todas las vistas.
     
  • Siempre necesitaremos especificar un tipo para @item en el primer parámetro genérico, incluso cuando no sea necesario. O sea, estas lambdas son obligatoriamente de la forma Func<T, IHtmlContent>, siendo T el tipo de item. Si el código de marcado no usa @item, podemos especificarlo como object o dynamic y luego pasar un nulo al invocarlo:
    Func<object, IHtmlContent> Time = @<h1>@DateTime.Now</h1>;
    ...
    @Time(null)
En definitiva, aunque con la solución que hemos visto podemos acercarnos algo, aún estamos lejos de nuestro querido @helper. Afortunadamente, en muchos issues de Github podemos encontrar referencias y comentarios relativos a la intención inicial del equipo de ASP.NET Core de traerlo de vuelta, aunque ciertamente no existen fechas ni señales del avance en este sentido :(

Publicado en Variable not found.

Aún no hay comentarios, ¡sé el primero!