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!
lunes, 8 de mayo de 2017
miércoles, 3 de mayo de 2017
Los que llevamos tiempo trabajando con paquetes NuGet, sabemos que la desinstalación de paquetes requería tradicionalmente entrar en la consola del gestor de paquetes, o bien usar el interfaz gráfico de este gestor de paquetes en Visual Studio, lo que era bastante lento y farragoso.

Y claro, como los humanos somos animales de costumbre, lo normal es que cuando damos el salto a ASP.NET Core continuemos haciéndolo de la misma forma, sin pararnos un segundo a replantearnos si hay mejores formas… lo que me recuerda a esta famosa imagen que anda por Internet desde hace bastante tiempo:

No gracias, no quiero perder el tiempo probando esas ruedas redondas porque estoy demasiado ocupado tirando de mi carro con ruedas cuadradas
(Fuente: Ni idea)

martes, 2 de mayo de 2017
Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET/.NET Core

martes, 25 de abril de 2017
C#Pues ya con la séptima versión de C# en la calle, aparecida de la mano del flamante Visual Studio 2017, va siendo hora de echar un vistacillo rápido a las principales novedades que encontraremos en esta nueva iteración de nuestro lenguaje favorito.

Y hoy vamos a comenzar con las funciones locales, una nueva capacidad que nos permitirá crear funciones locales a un ámbito, y que no serán visibles desde fuera de éste. Por ejemplo, podemos crear funciones en el interior de métodos, constructores, getters o setters, etc., pero éstas sólo serán visibles desde el interior del miembro en el que han sido declaradas.

Puede ser útil en determinados escenarios, puesto que evitan la introducción de "ruido" en las clases cuando determinado código sólo se va a consumir en el interior de un método, y al mismo tiempo pueden contribuir a mejorar la legibilidad y robustez del código.
lunes, 24 de abril de 2017
Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET/.NET Core


martes, 18 de abril de 2017
Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET/.NET Core

lunes, 10 de abril de 2017
Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET/.NET Core

martes, 4 de abril de 2017
ASP.NET Core MVCComo sabemos, tradicionalmente los controladores MVC son clases cuyo nombre, según la convención, debe finalizar por “Controller”, como en InvoiceController o CustomerController, y esta convención ha continuado en ASP.NET Core MVC, la edición más reciente del framework.

Sin embargo, desde las primeras versiones del framework la convención era modificable y podíamos adaptarla a nuestras necesidades aprovechando la extensibilidad del framework. De hecho, ya vimos hace muuucho mucho tiempo cómo hacerlo con la versión "clásica" de ASP.NET MVC, pero con la llegada de MVC Core las cosas han cambiado bastante.

En este post vamos a ver cómo modificar la convención de nombrado de controladores a algo más patrio: haremos que éstos puedan llamarse “ControladorDeXYZ”, como en ControladorDeFacturas o ControladorDeClientes. Es decir, si tenemos una clase como la siguiente, pretendemos que una petición hacia "/facturas/index" retorne el texto "ControladorDeFacturas.Index":
public class ControladorDeFacturas : Controller
{
    public IActionResult Index()
    {
        return Content("ControladorDeFacturas.Index");
    }
}
Por supuesto, podríamos hacer que esta clase fuera un controlador simplemente aplicándole el atributo [Controller], pero el objetivo de este post es aprender algo sobre el funcionamiento interno del framework, así que no vamos a quedarnos con esta solución tan sencilla ;)

Pero antes de ponernos a ello, permitidme aclarar que cambiar las convenciones de nombrado de controladores no es muy conveniente porque, aparte de romper el principio de la mínima sorpresa, hay herramientas que podrían dejar de funcionar correctamente, pero sin duda hacerlo ofrece una magnífica ocasión para profundizar un poco en los entresijos del framework ;)
lunes, 3 de abril de 2017
miércoles, 29 de marzo de 2017
Desarrollador volviéndose loco
Imagen original de Pixabay.
La llegada del próximo April Fool's day, algo parecido a lo que por aquí conocemos como el día de los Inocentes, me ha recordado una curiosidad con la que me topé hace algún tiempo que, si tenéis un poco de maldad reprimida, podéis utilizar para gastar una broma a algún compañero desarrollador y echar unas risas.

La historia consiste en abusar del amplio conjunto de caracteres soportado por UTF, sustituyendo el punto y coma de finalización de una línea de código (";") por el símbolo de interrogación griego (";", Unicode 037E), indistinguibles a simple vista, como en la siguiente línea:
public void HelloWorld()
{
    Console.WriteLine("Hello world!");
}
lunes, 27 de marzo de 2017
Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET/.NET Core

martes, 21 de marzo de 2017
ASP.NET Core MVCSabemos que mientras se renderiza una vista Razor, por defecto el framework MVC va almacenando el resultado en memoria, y sólo al finalizar es cuando comienza a retornarlo al lado cliente.

Por ejemplo, en la ejecución del siguiente código Razor, el usuario que solicitó la página no vería absolutamente nada durante 10 segundos, y de pronto le llegaría el resultado completo:
@using System.Threading.Tasks
@{
    Layout = null;
}
<html>
<head>
    <title>Hello world!</title>
</head>
<body>
    <h1>Let's go</>
    <ul>
        @for (int i = 0; i < 10; i++)
        {
            await Task.Delay(1000);
            <li>@i</li>
        }
    </ul>
</body>
</html>
Nota: Observad que para hacer el retardo, en lugar del típico Thread.Sleep() he utilizado Task.Delay() sólo para recordaros que en ASP.NET Core las vistas se renderizan/ejecutan en un contexto asíncrono y, por tanto, podemos utilizar en su interior llamadas con await como hacemos en otros puntos del código.

lunes, 20 de marzo de 2017
Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET/.NET Core

martes, 14 de marzo de 2017
ASP.NET CoreEl sistema de inyección de dependencias de ASP.NET Core es un potente mecanismo que viene de serie en el framework y, que de hecho, es uno de los principales pilares en los que se basa su funcionamiento.

Probablemente sabréis (y si no, podéis echar un vistazo a este post) que existen diversas fórmulas para añadir servicios o componentes al contenedor de dependencias, y una de ellas es la denominada "Scoped". Estos componentes quedan registrados asociados a un ciclo de vida específico (ServiceLifetime.Scoped), que indica que cada vez que haya que se solicite un objeto de este tipo se retornará la misma instancia dentro el ámbito actual, que normalmente coincide con el proceso de una petición específica.

O en otras palabras, dentro de la misma petición, la instancia del componente será compartida por todos los objetos que dependan de él. Además, al finalizar el proceso de la petición, el framework invocará su método Dispose() (si existe, claro), permitiendo liberar los recursos que haya utilizado. Por ejemplo, suele ser una buena práctica emplear esta técnica para reutilizar un contexto de datos entre los servicios que participan en el proceso de una petición que accede a una base de datos, y asegurar su liberación final para no dejar conexiones abiertas.

Pero este post no va de ver cómo registrar estos componentes o de cómo utilizarlos en nuestras aplicaciones, sino de responder una simple curiosidad: ¿quién se encarga de crear este scope cuando comienza una petición y de liberarlo cuando finaliza? Ya, sé que no tiene mucha utilidad práctica en el día a día, pero es una buena excusa para echar un vistazo y entender cómo funcionan las cosas por dentro ;)

<Disclaimer>Todo lo que comentaremos a continuación son detalles de la implementación actual del framework y son válidos en la versión 1.1 de ASP.NET Core, pero podrían cambiar en futuras versiones.</Disclaimer>

lunes, 13 de marzo de 2017
Enlaces interesantesAquí tenéis una nueva colección de enlaces interesantes, con especial atención al lanzamiento de Visual Studio 2017 :)

Por cierto, a partir de ahora voy a utilizar otro criterio de categorización, uniendo .NET y .NET Core en una única categoría, y haciendo lo mismo con ASP.NET y ASP.NET Core, porque cada vez iba teniendo menos sentido mantener esta separación.

Como siempre, espero que estos links os resulten interesantes. :-)

.NET/.NET Core

ASP.NET/ASP.NET Core

Azure / Cloud

Conceptos/Patrones/Buenas prácticas

Data

Html/Css/Javascript

Visual Studio/Complementos/Herramientas

Cross-platform

Otros


Publicado en Variable not found
martes, 7 de marzo de 2017
Publish Azure WebJobDesde hace algún tiempo estoy sufriendo un error que aparece justo en el momento de publicar un Webjob a Azure desde Visual Studio 2015.

Supongo que tendrá su motivo y se deberá a que estoy haciendo algo mal, pero bueno, el caso es que el error es un poco molesto porque impide la publicación del proyecto y, aunque no es difícil de solucionar, siempre me obliga a perder unos minutos en buscar una solución y aplicarla a mi proyecto.

El error que podemos ver en la ventana de resultados es el siguiente:
Error : El argumento 'DefaultConnection-Web.config Connection String' no puede ser NULL ni estar vacío.
O su versión en inglés:
Error : The 'DefaultConnection-Web.config Connection String' argument cannot be null or empty.
Así que, a modo de nota mental, y si acaso poder echar una mano a alguno que os encontréis ante el mismo escenario, comento dos soluciones que me han funcionado bien. Simplemente elegid la que más os convenza.

Solución 1

Es la más sencilla, y consiste únicamente en eliminar la carpeta /obj del proyecto en cuestión. Tras ello, volvemos a publicar y funcionará todo bien.

Solución 2

La segunda solución es algo más compleja, aunque tampoco para echarse las manos a la cabeza.

El problema está en el archivo de publicación (.pubxml) que estáis usando para publicar el WebJob, que por algún motivo ha perdido la cadena de conexión por defecto del proyecto. Podéis encontrarlo en la carpeta /Properties y tiene una sección como la siguiente:
<PublishDatabaseSettings>
  <Objects>
    <ObjectGroup Name="DefaultConnection" Order="1" Enabled="False" xmlns="">
      <Destination Path="" />
      <Object Type="DbCodeFirst">
        <Source Path="DBMigration" 
           DbContext="MyProject.MyDataContext, MyProject" 
           MigrationConfiguration="MyProject.Migrations.Configuration, MyProject" 
           Origin="Convention" />
      </Object>
    </ObjectGroup>
  </Objects>
</PublishDatabaseSettings>
Lo único que hay que hacer para poder publicar sin problema es transformar la cuarta línea (el tag <Destination>) de la siguiente forma:
<PublishDatabaseSettings>
  <Objects>
    <ObjectGroup Name="DefaultConnection" Order="1" Enabled="False" xmlns="">
      <Destination Path="{deployment connection string}" /> 
      <Object Type="DbCodeFirst">
        <Source Path="DBMigration" 
           DbContext="MyProject.MyDataContext, MyProject" 
           MigrationConfiguration="MyProject.Migrations.Configuration, MyProject" 
           Origin="Convention" />
      </Object>
    </ObjectGroup>
  </Objects>
</PublishDatabaseSettings>
Es decir, establecemos el atributo Path del tag <Destination> al valor "{deployment connection string}" y lo tendremos solucionado.

¡Y eso es todo! En fin, este post trata sobre esos misterios que suceden de vez en cuando y nos hacen dedicar minutos de nuestro preciado tiempo a labores de fontanería. Espero que lo descrito aquí os sea de utilidad en algún momento... o no, porque significaría que no se os ha dado nunca este caso, y eso no es mala cosa ;)

Publicado en Variable not found.
lunes, 6 de marzo de 2017
Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET

lunes, 27 de febrero de 2017
Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET

martes, 21 de febrero de 2017
Aunque IIS Express está diseñado principalmente para ser utilizado por desarrolladores en el interior su equipo de trabajo, seguro que la mayoría sabéis que haciendo un par de cambios en la configuración también es posible utilizarlo desde equipos externos, por ejemplo para poder hacer pruebas de una web o servicio desde otros dispositivos conectados a la misma red.

Es sencillo encontrar cómo hacerlo porque hay mucho escrito al respecto en la red, y sin embargo de vez en cuando me encuentro con desarrolladores que no saben que esto es posible hacerlo, así que este post va por vosotros ;D

Partiremos de un proyecto ASP.NET 4.x creado en Visual Studio 2015 o 2017, da igual si se trata de una aplicación MVC, Web Forms, Web API o lo que sea. Para desarrollar el ejemplo, imaginemos que al ejecutarlo en local estamos usando la URL http://localhost:3803/.

Veamos paso a paso cómo acceder a esta aplicación desde otro equipo conectado a la red local, y cómo solucionar algunos de los problemas que podemos encontrar por el camino.

lunes, 20 de febrero de 2017
Happy 15th Birthday .NET!Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET

martes, 14 de febrero de 2017
ASP.NET CoreHace algunos meses comentábamos por aquí cómo en ASP.NET Core es posible modificar los archivos de configuración de una aplicación en caliente, sin necesidad de detenerla, siendo los cambios aplicados de forma inmediata.

En aquél momento ya vimos que era realmente sencillo conseguirlo cuando usábamos settings no tipados, bastaba con añadir el parámetro reloadOnChanges a la hora de añadir el origen de configuración, como en el siguiente ejemplo:
public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
        .AddEnvironmentVariables();
    Configuration = builder.Build();
}
Sin embargo, también vimos que conseguir lo mismo cuando queríamos acceder a los settings de forma tipada era algo más engorroso, puesto que había que configurar manualmente el proceso de recarga y bindeado de datos con la instancia de la clase de configuración, para poder acceder luego a ella a través de un objeto IOptions<T> disponible en el contenedor de dependencias.
lunes, 13 de febrero de 2017
martes, 7 de febrero de 2017
ASP.NET Core MVCDurante el proceso de negociación de contenidos en un API desarrollado con ASP.NET Core MVC, lo habitual es que el output formatter utilizado para componer el resultado enviado de vuelta al cliente sea seleccionado a partir de lo indicado por el cliente en la cabecera Accept de la petición HTTP, pero en este post vamos a ver que esto no tiene por qué ser necesariamente así.

Por ejemplo, supongamos que tenemos una aplicación MVC con un controlador que expone un servicio como el siguiente:
[Route("api/contacts")]
public class ContactsController : Controller
{
    private readonly IContactRepository _repository;

    public ContactsController(IContactRepository repository)
    {
        _repository = repository;
    }

    [HttpGet("{id}")]
    public IActionResult Get(int id)
    {
        var contact = _repository.Get(id);
        if (contact == null)
            return NotFound();
        return Ok(contact);
    }
}
Esta acción, que retornaría un objeto de tipo Contact del modelo de nuestra aplicación, podría ser fácilmente utilizada desde otras capas o sistemas, por ejemplo como sigue:
// Petición:
GET http://localhost:2805/api/contacts/1 HTTP/1.1 
Accept: application/json

// Respuesta:
HTTP/1.1 200 OK 
Content-Type: application/json; charset=utf-8  
Content-Length: 51

{"id":1,"name":"John Smith","phone":"998-12-32-12"}
lunes, 6 de febrero de 2017
Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET

martes, 31 de enero de 2017
.NET CoreHace unos días hablábamos de que próximamente veremos cambios en los archivos de proyecto de las aplicaciones .NET Core, que dejarán de utilizar el popular project.json para volver al tradicional .csproj, aunque rejuvenecido y potenciado para hacerlo más versátil y utilizable en los nuevos entornos.

Para los que ya hemos comenzado a crear aplicaciones y bibliotecas ASP.NET Core, este cambio implica que en algún momento deberemos actualizarlas al nuevo formato de proyectos. Y como ya adelantamos, este proceso no va a resultar especialmente doloroso aunque obviamente tendremos que saber cómo hacerlo.

En este post vamos a tratar tres posibles escenarios de actualización:
Hey, pero antes de continuar, el tradicional disclaimer: tened en cuenta que tanto Visual Studio 2017 como el tooling de .NET Core está aún en preview, así que hay cosas que podrían variar en el futuro próximo.
lunes, 30 de enero de 2017
martes, 24 de enero de 2017
Archivo de proyecto JSONProbablemente muchos recordaréis que cuando comenzaron a verse las primeras previews de ASP.NET Core, por entonces aún llamado ASP.NET vNext, una de las novedades más sorprendentes que pudimos descubrir fue la aparición de un nuevo archivo de proyecto, llamado project.json, que sustituiría al vetusto .csproj (o vbproj).

La comunidad se entusiasmó bastante con la idea porque el nuevo archivo de proyecto era bastante más simple y liviano que el tradicional .csproj, daría menos problemas con los sistemas de control de código fuente, era fácil de leer y de editar sin necesidad de disponer de Visual Studio o un IDE completo, y por tanto era muy portable entre plataformas. Y encima usaba el formato JSON, que sin duda resultaba mucho más cool que XML. ¿Qué más podíamos pedir?

Antes de continuar, permitidme un inciso: aunque conceptualmente todo lo que vamos a contar es cierto en este momento (enero/2017) y probablemente seguirá siéndolo, el tooling aún está en desarrollo y, por tanto, algunos detalles todavía podrían cambiar.
lunes, 23 de enero de 2017
Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET

martes, 17 de enero de 2017
ASP.NET Core MVCComo sabemos, para invocar a un view component e incluir la vista parcial que retorna en el interior de otra vista, debemos utilizar desde ésta el helper @Component.Invoke() o su alternativa asíncrona @Component.InvokeAsync(), por ejemplo de la forma que vemos a continuación:
<div class="cart">    
   @await Component.InvokeAsync(
      "ShoppingCart", 
      new { showImages = false, showButtons = false }
   )
</div>
Y aunque no es especialmente incómodo ni difícil de implementar, es cierto que presenta algunos inconvenientes. En primer lugar, dado el helper @Component.Invoke() es el mismo para todos los view components, ni el entorno ni el compilador pueden ofrecernos ayuda en nombres o parámetros, ni validar que la llamada sea correcta. Cualquier fallo se detectará exclusivamente en tiempo de ejecución.

Asimismo, está claro que el código de las vistas es más legible y fluido si en lugar de utilizar sintaxis imperativa, como son las llamadas a helpers, se utiliza un enfoque declarativo, esto es, si utilizamos etiquetas como los célebres tag helpers.

lunes, 16 de enero de 2017
Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET

martes, 10 de enero de 2017
lunes, 9 de enero de 2017
The best of 2016Como las tradiciones están para cumplirlas, aprovecharemos este primer post del año para hacer el clásico repaso de los diez artículos de 2016 que fueron más visitados durante el año que acabamos de cerrar.

He de decir que esta vez he tenido que manipular un poco los resultados porque muchos de los posts más visitados eran los relativos a los anuncios de la gran celebración del décimo aniversario del blog y los espectaculares sorteos y regalos (como éste, éste, este, éste, éste…) que repartimos gracias a nuestros patrocinadores. Por tanto, para no monopolizar el ranking sin añadir mucho valor a estas alturas, no los he tenido en cuenta.

Ya centrados en los artículos con más chicha, veremos que la gran mayoría de entradas destacadas tienen que ver con ASP.NET Core, lo que pone de manifiesto el interés que está despertando el nuevo framework, y dejan claro que vosotros, amigos del blog, sois gente inquieta y os gusta estar a la última ;)

Encabeza el ranking el post "ASP.NET 5 se llama ahora ASP.NET Core", un eco del controvertido anuncio de Microsoft anunciando el cambio de nombre de su nuevo framework de desarrollo para la web. Aunque conceptualmente fue un renombrado correcto, no se puede decir lo mismo del momento que eligieron para hacerlo, que sin duda fue demasiado tarde.

En segunda posición encontramos "¿Cuál es el "Bus factor" de tu proyecto?" una llamada de atención sobre los peligros de concentrar toda la información y conocimiento sobre un proyecto en un grupo reducido de personas. Un tema serio, independientemente de lo divertido del término.

Le sigue en el ranking el artículo "5 cambios destacables en ASP.NET Core RC2", donde comentábamos las principales novedades introducidas en la tardía y rompedora segunda release candidate del nuevo marco de trabajo. Aquí comenzaron a verse aplicados los cambios de nombre, el nuevo modelo de aplicaciones de consola ASP.NET  y el descarte de DNX en favor de .NET Core CLI.

El siguiente post más visto fue el que se hacía eco del lanzamiento de la versión 1.0 RTM de .NET Core, ASP.NET Core y Entity Framework Core. Era sin duda un esperado acontecimiento, probablemente el más importante de los últimos años, y era previsible que el tema despertara interés.

A continuación encontramos un artículo con contenido puramente técnico donde explorábamos el uso de variables de sesión en ASP.NET Core 1.0. Aunque a veces denostadas, probablemente por el abuso que históricamente se ha hecho de ellas, las variables de sesión son un recurso útil para el mantenimiento de estado entre peticiones de una aplicación web, y el interés despertado por este contenido dejó claro que aún siguen formando parte de la caja de herramientas de los desarrolladores.

En sexto lugar tenemos un post autorespondiéndome a una curiosidad que arrastraba desde hacía tiempo. En ¿Es ASP.NET Core MVC un middleware? estudiábamos si existía un middleware específico de MVC que fuera el responsable de "enganchar" este framework al pipeline de ASP.NET Core. Spoiler: no, no existe.

En "Convenciones personalizadas en ASP.NET Core MVC" introducíamos el Application Model de MVC, y cómo aprovecharlo para construir convenciones custom en las aplicaciones, como añadir automáticamente el filtro [ValidateAntiForgeryToken] a todas las acciones accesibles a través del método POST.

"ASP.NET Core" en Google TrendsSeguidamente encontramos entre los posts más vistos el anuncio del lanzamiento de mi Curso de ASP.NET Core MVC en CampusMVP, demostrando de nuevo el interés de la comunidad de desarrolladores en esta nueva tecnología, y que reflejaba en el gráfico adjunto. Aún estáis a tiempo de echar un vistazo al artículo para decidir si lo empezáis mañana mismo ;)

Y finalizamos el top ten con un empate entre dos posts puramente técnicos, también sobre ASP.NET Core. El primero de ellos era el inicio de la serie "Archivos estáticos en aplicaciones ASP.NET Core", que se extendió posteriormente durante tres artículos más. El segundo, es una reedición de un artículo anterior, actualizada a versiones más reciente de ASP.NET Core, tras los cambios introducidos en RC2: "Logging en ASPNET Core (actualizado a RC2)".

Aunque ya hemos completado el ranking de los diez posts más visitados, voy a hacer una excepción para incluir el que hace número 11, porque tiene si mérito: Visual Studio 2017 se llamará finalmente Visual Studio Core 1.0. Y no queda ahí la cosa… Pues sí, la broma escrita para el pasado día de los inocentes (28-dic) entró con fuerza y en sólo tres días se quedó en las puertas de estar entre los diez artículos más vistos del año pasado :DD

Como siempre, aparte de los contenidos generados durante 2016, hemos tenido bastantes visitas a posts que ya son clásicos en el blog y supongo que estarán muy bien posicionados en buscadores, como:
Y un año más, por su alta situación en el ranking, me gustaría destacar el excelente artículo “Closures en JavaScript: entiéndelos de una vez por todas”, del amigo Óscar Sotorrío, el único que ha sido capaz de publicar como blogger invitado en Variable Not Found. ¡A ver si algunos más os animáis, las puertas están abiertas!

Y esto es todo! Espero que os haya resultado interesante para conocer algún artículo que os perdisteis en su momento o para rememorar algunos que os llamaron la atención ;)

Publicado en Variable not found.