martes, 14 de enero de 2020
Las Razor Class Libraries (RCL) constituyen una interesante fórmula para crear componentes redistribuibles de interfaz de usuario para aplicaciones basadas en ASP.NET Core MVC o Razor Pages. En las bibliotecas de clases de este tipo podemos incluir controladores, view components, tag helpers o vistas y páginas Razor, elementos que estarán disponibles en las aplicaciones que las referencien, bien directamente o bien a través del paquete NuGet en el que las distribuyamos.
Sin embargo, es menos conocido el hecho de que estas bibliotecas pueden incluir también recursos estáticos como imágenes, hojas de estilo o scripts, lo que resulta bastante interesante a la hora de crear componentes totalmente autosuficientes y muy reutilizables.
En este post vamos a ver cómo crear una RCL redistribuible que definirá el tag helper
Dado que vamos a utilizar estas tres imágenes, debemos añadirlas a la carpeta
Por defecto, todos los recursos presentes en la carpeta
Por ejemplo, si nuestro proyecto RCL se denomina
En este momento, si modificamos el tag helper de la siguiente forma, ya deberíamos poder ver a Mario, aún quietecito, en las páginas que utilicen el tag
Sólo un detalle adicional: esto os funcionará sin problema cuando publiquéis el proyecto o si lo ejecutáis desde la carpeta de salida o el IDE en el entorno Development, pero no si modificáis el entorno a
Para conseguirlo, sólo tendremos que introducir algo de Javascript en el tag helper para que mueva el sprite y vaya alternando sus frames al mismo tiempo. Una posible implementación podría ser la siguiente:
¡Y eso es todo! Con esto ya tendremos a Mario correteando por la pantalla. Pero lo importante no es eso, sino que por el camino hemos aprendido a crear una RCL reutilizable con contenidos estáticos :)
Publicado en Variable not found.
Sin embargo, es menos conocido el hecho de que estas bibliotecas pueden incluir también recursos estáticos como imágenes, hojas de estilo o scripts, lo que resulta bastante interesante a la hora de crear componentes totalmente autosuficientes y muy reutilizables.
En este post vamos a ver cómo crear una RCL redistribuible que definirá el tag helper
<mario>
, cuya inclusión en una página hará que ésta muestre el conocido personaje correteando por la pantalla, como se muestra en la siguiente captura:1. Lo básico: creación y consumo de la Razor Class Library
Como sabemos, podemos crear RCLs utilizando Visual Studio o bien desde la línea de comandos:dotnet new razorclasslib --support-pages-and-views
Importante: en ambos casos es fundamental añadir el soporte para páginas y vistas a la hora de crear el proyecto.También podemos crear una biblioteca de clases tradicional, y modificar su archivo
.csproj
para dejarlo como el mostrado a continuación:<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
</Project>
Una vez creado el proyecto, ya podemos introducir en él los componentes que queramos distribuir en la biblioteca. En nuestro caso, iremos preparando el esqueleto del tag helper <mario>
, que podría ser algo así:public class MarioTagHelper: TagHelper
{
public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.SuppressOutput();
output.Content.SetHtmlContent("<p align=center>Mario will be here!</p>");
return base.ProcessAsync(context, output);
}
}
Para utilizar este componente desde una aplicación ASP.NET Core MVC, sólo tenemos que referenciar el proyecto RCL (o el paquete NuGet, si hubiéramos decidido distribuir así nuestra biblioteca) y, dado que se trata de un tag helper, registrarlo en el archivo _ViewImports.cshtml
. Suponiendo que la biblioteca Razor se denomina MarioRcl
, sería algo como:...
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, MarioRcl
De esta forma, ya podríamos utilizar en nuestras páginas la etiqueta que hemos definido, por ejemplo en la vista Index.cshtml
creada por defecto en proyectos MVC:...
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web
apps with ASP.NET Core</a>.</p>
</div>
<mario></mario>
El resultado en ejecución sería el siguiente:2. Incluir recursos estáticos
Por simplificar, en el código anterior solo hemos mostrado un texto en el lugar donde se introdujo la etiqueta<mario>
, aunque en realidad lo que nos interesará es insertar un código script que vaya superponiendo distintas imágenes para crear la ilusión de animación.Dado que vamos a utilizar estas tres imágenes, debemos añadirlas a la carpeta
wwwroot
del proyecto RCL, que sabemos que es donde se almacenan por convención los recursos estáticos; un buen lugar para hacerlo, sin duda, sería en una subcarpeta llamada images
en su interior.
Por defecto, todos los recursos presentes en la carpeta
wwwroot
de la RCL serán distribuidos junto con la biblioteca de clases Razor. De hecho, si probáis a publicar el proyecto ASP.NET Core MVC que referencia a la RCL, podréis observar que los recursos estáticos se encuentran en la carpeta de salida, en un directorio llamado por convención wwwroot\_content\[Ensamblado RCL]
.Por ejemplo, si nuestro proyecto RCL se denomina
MarioRcl
, los recursos estáticos introducidos en la carpeta wwwroot
de la Razor Class Library se introducirán automáticamente en la carpeta de salida wwwroot\_content\MarioRcl
del proyecto web que lo utilice, como se muestra en la siguiente captura de pantalla del explorador de archivos de Windows:Si hay recursos estáticos que no queremos incluir al empaquetar la RCL, podemos excluirlos explícitamente utilizando el elementoY con esto, podríamos decir que la magia está hecha. El único requisito adicional a tener en cuenta es que el proyecto web deberá incluir el middleware Static Files en el pipeline, pues es la forma de asegurar el proceso de peticiones a archivos estáticos.<DefaultItemExcludes>
del archivo.csproj
.
En este momento, si modificamos el tag helper de la siguiente forma, ya deberíamos poder ver a Mario, aún quietecito, en las páginas que utilicen el tag
<mario>
.public class MarioTagHelper : TagHelper
{
private static readonly string Root =
$"/_content/{typeof(MarioTagHelper).Assembly.GetName().Name}";
public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.SuppressOutput();
output.Content.SetHtmlContent(GetHtml());
return base.ProcessAsync(context, output);
}
private string GetHtml() =>
$"<p align=center><img src='{Root}/images/1.png'>";
}
Sólo un detalle adicional: esto os funcionará sin problema cuando publiquéis el proyecto o si lo ejecutáis desde la carpeta de salida o el IDE en el entorno Development, pero no si modificáis el entorno a
Production
. En este caso tendréis que añadir una configuración extra al Program.cs
:public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStaticWebAssets(); <-- ¡Añadir esta línea!
webBuilder.UseStartup<Startup>();
});
Punto extra: démosle vida al muñeco
Ya sabemos todo lo necesario para incluir recursos estáticos en una RCL y distribuirlos con ella, así que podríamos considerar que este último punto sobra en el post. Pero como habíamos establecido al principio, el objetivo era ver corretear a Mario por pantalla, así que démosle un último empujón.Para conseguirlo, sólo tendremos que introducir algo de Javascript en el tag helper para que mueva el sprite y vaya alternando sus frames al mismo tiempo. Una posible implementación podría ser la siguiente:
public class MarioTagHelper : TagHelper
{
private static readonly string Root =
$"/_content/{typeof(MarioTagHelper).Assembly.GetName().Name}";
public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.SuppressOutput();
var id = context.UniqueId; // ID único del tag <mario> en proceso,
// generado por Razor
output.Content.SetHtmlContent(GetHtml(id));
return base.ProcessAsync(context, output);
}
private string GetHtml(string id) =>
$@"<div style='width=100%;' id='parent-{id}'>
<img id='mario-{id}' style='position: absolute; left: 0;'>
</div>
<script>
(function () {{
let frame = 0;
let parent = document.getElementById('parent-{id}');
let element = document.getElementById('mario-{id}');
let left = parseInt(element.style.left);
setInterval(function() {{
element.src = '{Root}/images/' + frame + '.png';
element.style.left = left+'px';
left=(left+10)%(parent.offsetWidth-element.offsetWidth);
frame = (frame+1) % 3;
}}, 80);
}})();
</script>";
}
¡Y eso es todo! Con esto ya tendremos a Mario correteando por la pantalla. Pero lo importante no es eso, sino que por el camino hemos aprendido a crear una RCL reutilizable con contenidos estáticos :)
Publicado en Variable not found.
Aún no hay comentarios, ¡sé el primero!
Enviar un nuevo comentario