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 noviembre de 2019
ASP.NET CoreHace ya algún tiempo nos preguntábamos que dónde había ido a parar la directiva @helper de Razor en ASP.NET Core, y la respuesta era simple: había desaparecido.

Como recordaréis, esta directiva era bastante útil para simplificar el código de las vistas y mejorar su legibilidad, pues permitía crear funciones reutilizables que mezclaban HTML y código de servidor, como en el siguiente ejemplo:
@* 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>
}
Hasta la versión 2.2, teníamos que conformarnos con apaños como los descritos en aquél post si queríamos emular lo que llevábamos tantos años utilizando con MVC 5 y anteriores. Y también entonces comentamos que había ciertas posibilidades de que en algún momento volviera a la vida, y éstas se han materializado, por fin, en ASP.NET Core 3.0.

Aunque quizás más bien habría que hablar de reencarnación...

¿Cómo implementar funciones con código de marcado?

La nueva forma de implementar bloques de código reutilizables mezclando C# y HTML en el interior de una vista ya no se basa en la directiva @helper. Ahora, simplemente podemos introducir código de marcado en funciones declaradas localmente o en el interior de bloques @functions de Razor.

Observad el siguiente ejemplo, donde creamos una función Multiplication() que mezcla código HTML y C# para generar una tabla de multiplicación:
@{
    Multiplication(2);
    Multiplication(3);
}

@functions
{
    void Multiplication(int x)
    {
        <h2>Multiplication table of @x</h2>
        <ul>
            @for (var i = 1; i <= 10; i++)
            {
                <li>@x * @i = @(x * i)</li>
            }
        </ul>
    }
}
Con esto podríamos considerar que tenemos de vuelta la directiva @helper, aunque sea utilizando esta nueva sintaxis. Sin embargo, hay algunos aspectos adicionales a tener en cuenta.

Por ejemplo, si la función utilizara internamente asincronía, tendríamos que definirla e invocarla de forma diferente, como en el siguiente ejemplo:
@{
    await SlowMultiplication(2);
    await SlowMultiplication(3);
}

@functions
{
    async Task SlowMultiplication(int x)
    {
        await Task.Delay(5000);
        <h2>Multiplication table of @x</h2>
        <ul>
            @for (var i = 1; i <= 10; i++)
            {
                <li>@x * @i = @(x * i)</li>
            }
        </ul>
    }
}
Otro aspecto sumamente importante es que, a diferencia de la clásica directiva @helper, estas funciones renderizan directamente el contenido y no retornan ningún valor, por lo que no se pueden utilizar como expresiones directas:
<h1>Current date: @DateTime.Now</h1>
<div>
    @Multiplication(1) <!-- Error: Multiplication() retorna void -->
</div>
-->
Aunque si quisiéramos simular este comportamiento siempre podríamos forzar un retorno, aunque fuera nulo o vacío, de la siguiente forma:
<h1>Current date: @DateTime.Now</h1>
<div>
    @Multiplication(1)
</div>

@functions
{
    string Multiplication(int x)
    {
        <h2>Multiplication table of @x</h2>
        <ul>
            @for (var i = 1; i <= 10; i++)
            {
                <li>@x * @i = @(x * i)</li>
            }
        </ul>
        return string.Empty;
    }
}
Por último, es interesante destacar que también podemos introducir la mezcla de código HTML y C# en funciones locales de C# implementadas dentro de la propia página Razor, como en el siguiente ejemplo:
@{ 
    void ShowCurrentDate()
    {
        <div class="date">@DateTime.Now</div>
    }

    ShowCurrentDate();
}

¿Y ese tipo de funciones son reutilizables?

Pues me temo que no, al menos de momento. Hasta donde he podido ver, no existe ninguna forma para reutilizar este tipo de funciones; su ámbito es local a la página donde han sido definidas con @functions. Ni siquiera definiéndolas en vistas especiales como _ViewImports.cshtml o _ViewStart.cshtml están accesibles desde el resto de vistas.

Pero que no cunda el pánico ;) Recordad que si queremos reutilizar ese tipo de código entre varias vistas, siempre podemos utilizar cualquiera de los mecanismos que ASP.NET Core MVC proporciona para ello: vistas parciales, tag helpers, helpers HTML o view components.

Publicado en: www.variablenotfound.com.

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