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!
viernes, 28 de diciembre de 2018
.NET Core Desde que apareció Roslyn, C# ha ido evolucionando a pasos agigantados. Tanto es así que es frecuente encontrar desarrolladores que, aunque lo usan a diario, desconocen todo su potencial porque la velocidad de introducción de cambios en el lenguaje es mayor que la de asimilación de novedades por parte de los profesionales que nos dedicamos a esto.

Por ejemplo, en las consultorías técnicas que realizo en empresas es frecuente encontrar equipos de trabajo en los que aún no está generalizado el uso de construcciones tan útiles como el null coalescing operator (fullName ?? "Anonymous"), safe navigation operator (person?.Address?.Street), el at object operator (Address@person), o características tan potentes como las funciones locales, interpolación de cadenas, tuplas o muchas otras.

Sin embargo, creo que el rey de los desconocidos es el operador virgulilla "~" de C#. Introducido con C#7 es probablemente uno de los operadores menos utilizados y, sin embargo, de los más potentes ofrecidos por el lenguaje.
Nota de traducción: el nombre original del operador es "tilde operator", y como he encontrado poca literatura al respecto en nuestro idioma, me he tomado la libertad de traducirlo como operador virgulilla (¡sí, esa palabra existe!). También, en entornos más informales lo encontraréis con el nombre "wormy operator" (operador gusanillo) o como "soft similarity operator" (que podríamos traducir como operador de similitud relajada).
lunes, 24 de diciembre de 2018
Enlaces interesantes, edición feliz navidad! Ahí van los enlaces recopilados durante la semana pasada y, como siempre, espero que os resulten interesantes :-)

Y de paso, aprovecho este momento  para desearos a todos unas felices fiestas y un grandioso 2019 en todos los ámbitos.

Por si te lo perdiste...

.NET / .NET Core

martes, 18 de diciembre de 2018
ASP.NET Core MVC Hace unos días publicaba un post sobre la mala idea que era tener controladores con demasiadas responsabilidades y cómo un constructor con demasiadas dependencias podía ser una señal (un 'code smell') de que las cosas no estaban yendo bien en ese sentido.

Por ejemplo, echando un vistazo al siguiente controlador podemos ver claramente una violación del Principio de Responsabilidad Única (SRP) en un controlador que conoce demasiados detalles sobre la forma de proceder al registrar un pedido:
public class OrderController: Controller
{
    private readonly IOrderServices _orderServices;
    [...] // Other private members

    public OrderController(IOrderServices orderServices, IUserServices userServices, 
        IMailingService mailingServices, ISmsServices smsServices, 
        IPdfGenerator pdfGenerator, IMapper mapper
    )
    {
        _orderServices = orderServices;       
        _userServices = userServices;
        [...] // Other assignments...
    }

    [HttpPost]
    public Task<IActionResult> Submit(OrderViewModel orderViewModel)
    {
        if(!ModelState.IsValid)
        {
            return View(orderViewModel);
        }
        var orderDto = _mapper.Map<OrderDto>(orderViewModel);
        var orderResult = await _orderServices.AddAsync(orderDto);
        if(!orderResult.Success)
        {
            return RedirecToAction("OrderError", new { error = orderResult.Error }));
        }
        var userPreferences = await _userServices.GetNotificationPreferencesAsync(CurrentUserId);
        var pdfUrl = await _pdfGenerator.GenerateOrderAsync(orderResult.Details);
        if(userPreferences.NotificationMode == NotificationMode.Sms)
        {
            await _smsServices.NotifyNewOrderAsync(orderResult.Details, pdfUrl);
        } 
        else 
        {
            await _mailingServices.NotifyNewOrderAsync(orderResult.Details);
        }
        return RedirectToAction("ThankYou", new { id = orderResult.Details.OrderId } );
    }
    ...
}
En dicho post comentaba también algunas cosas que podíamos hacer para solucionar el problema, así como una recomendación de lo que no debíamos hacer: disimular dependencias instanciando directamente componentes o utilizando otros "sabores" de inyección que hicieran menos evidente la relación de nuestra clase con otras de las que depende.

Pues bien, como hoy estamos algo rebeldes, vamos a ver las técnicas que nos permitirían hacerlo cuando sea necesario o, dicho de otra forma, qué alternativas tenemos para usar dependencias desde los controladores sin que estas sean suministradas mediante inyección en su constructor.
Precaución: estas técnicas son consideradas antipatrones o, como mínimo, code smells en la mayoría de los escenarios, así que usadlas poco, con precaución y siempre con conocimiento de causa ;)
lunes, 17 de diciembre de 2018
Enlaces interesantes Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET / .NET Core

martes, 11 de diciembre de 2018
La pasada semana, en el contexto del evento Microsoft Connect(); 2018, se lanzaron las últimas versiones de la familia de productos "Core": .NET Core 2.2, ASP.NET Core 2.2 y Entity Framework Core 2.2.

En todos los casos son revisiones pequeñas y que no rompen nada de lo anterior, pero en cada uno de estos productos se han introducido mejoras que vale la pena conocer, por lo que, antes que nada, os recomiendo que echéis un vistazo a los artículos anteriores, que son los anuncios oficiales.

En este post vamos a ver rápidamente las novedades más destacables de ASP.NET Core 2.2.
lunes, 10 de diciembre de 2018
Enlaces interesantes Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET / .NET Core

lunes, 3 de diciembre de 2018
Enlaces interesantes Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET / .NET Core

martes, 27 de noviembre de 2018
Desarrolladores Como sabemos, la inyección de dependencias está grabada a fuego en los genes de ASP.NET Core. La mayoría de sus componentes la usan internamente para obtener acceso a otros componentes que necesitan para cumplir sus funciones y, además, es una práctica recomendada en la parte que nos toca a nosotros como desarrolladores de aplicaciones.

Por ello, en ASP.NET Core MVC, lo habitual es que implementemos nuestros controladores atendiendo a este principio, y para ello utilicemos la técnica de inyección de dependencias en el constructor:
public class InvoiceController: Controller
{
    private readonly IInvoiceServices _invoiceServices;
    private readonly IMapper _mapper;
    private readonly ILogger<InvoiceController> _logger;

    public InvoiceController(
        IInvoiceServices invoiceServices, 
        ILogger<InvoiceController> logger,
        IMapper mapper)
    {
        _invoiceServices = invoiceServices;
        _logger = logger;
        _mapper = mapper;
    }
    ...
}
Nota: aunque en este post estemos hablando de controladores ASP.NET Core MVC, las ideas que vamos a comentar aquí son también aplicables a ASP.NET MVC "clásico" e incluso a otro tipo de frameworks que comparten los mismos conceptos.
lunes, 26 de noviembre de 2018
Enlaces interesantes Ahí van los enlaces recopilados durante la semana pasada, algo más escasa de lo habitual debido a los festivos en USA. Pocos, pero espero que interesantes :-)

Por si te lo perdiste...

.NET / .NET Core

martes, 20 de noviembre de 2018
ASP.NET Core MVC Seguramente habréis notado que en proyectos ASP.NET Core 2.1 la compilación de las vistas funciona de forma ligeramente diferente a como se hacía en versiones anteriores. Hasta ahora las vistas sólo eran compiladas al publicar el proyecto pero, a partir de esta versión, este proceso se realizará antes, durante la compilación.

En este artículo vamos a ver cómo aprovechar las ventajas de la precompilación, y al mismo tiempo mantener la flexibilidad que nos ofrece la compilación en tiempo de ejecución que tradicionalmente hemos disfrutado en proyectos ASP.NET y ASP.NET Core.

lunes, 19 de noviembre de 2018
Enlaces interesantes
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET / .NET Core

martes, 13 de noviembre de 2018
ASP.NET Core MVCEn el post anterior veíamos cómo personalizar los mensajes de error generados durante el proceso de binding, y cómo aprovechar las posibilidades que nos brinda el framework para introducir textos localizados en esos puntos.

Hoy seguiremos profundizando en este tema, pero esta vez nos centraremos en modificar los textos por defecto de las anotaciones de datos y hacer que simplemente decorando una propiedad con un atributo como Required consigamos obtener mensajes de error localizados y a nuestro gusto, sin necesidad de establecer el ErrorMessage de forma explícita y, en algunos casos, ni siquiera tener que indicar dicho atributo.
lunes, 12 de noviembre de 2018
Enlaces interesantes Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET / .NET Core

martes, 6 de noviembre de 2018
ASP.NET Core MVCEn el framework ASP.NET Core MVC es muy sencillo establecer los mensajes de error de validación de campos utilizando propiedades de las data annotations, como en el siguiente ejemplo:
namespace LocalizationDemo.ViewModels
{
    public class PersonViewModel
    {
        [Required(ErrorMessage ="The name is required")]
        public string Name { get; set; }
    }
}
Incluso es bastante fácil hacer que este texto aparezca traducido atendiendo a la cultura del hilo actual. Para ello, simplemente debemos configurar los servicios de localización apropiadamente, e indicar en la propiedad ErrorMessage la clave del mensaje de error en el archivo RESX asociado a la clase:
// En Startup.cs:
public void ConfigureServices()
{
    ...
    services.AddLocalization(opt=>opt.ResourcesPath="Resources");
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
        .AddViewLocalization()
        .AddDataAnnotationsLocalization(); // Esta línea añade la localización 
                                           // de data annotations 
    }

// En el view model:
namespace LocalizationDemo.ViewModels
{
    public class PersonViewModel
    {
        // El mensaje de error está definido 
        // en Resources/ViewModels.PersonViewModel.resx
        [Required(ErrorMessage ="NameIsRequired")] 
        public string Name { get; set; }
    }
}
Esto es así de fácil para las validaciones que declaramos de forma explícita en nuestro código, mediante atributos de anotaciones de datos. Sin embargo, existen otro tipo de validaciones que se realizan de forma implícita (por ejemplo, cuando en un campo entero introducimos un valor no numérico) y cuyos mensajes de error no son tan sencillos de establecer.
lunes, 5 de noviembre de 2018
Enlaces interesantes
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET / .NET Core

lunes, 29 de octubre de 2018
Enlaces interesantes
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET / .NET Core

martes, 23 de octubre de 2018
ASP.NET Core MVC Desde que comenzamos a programar con ASP.NET MVC tenemos interiorizado que si en nuestras acciones vemos código repetido, suele ser un candidato a ser implementado en forma de filtro. Así, durante años hemos implementado en forma de action filters asuntos transversales de nuestras aplicaciones, como la seguridad, logging, caching y otros aspectos.

Sin embargo, a veces olvidamos que estas mismas técnicas podemos utilizarlas para simplificar código en la implementación de convenciones o funciones más ligadas al negocio o a funcionalidades de nuestra aplicación. Por ejemplo, ¿no estáis aburridos de escribir acciones como las siguientes?
public class FriendsController: Controller
{
    public IActionResult View(int id) 
    {
        var friend = _friendServices.GetById(id);
        if(friend == null)
           return NotFound();
        ... // Prepare and show "View" view
    }

    public IActionResult Edit(int id) 
    {
        var friend = _friendServices.GetById(id);
        if(friend == null)
           return NotFound();
        ... // Prepare and show "Edit" view
    }

    public IActionResult Delete(int id) 
    {
        var friend = _friendServices.GetById(id);
        if(friend == null)
           return NotFound();
        ... // Prepare and show "Delete" view
    }

    ...
}
Pues bien, vamos a aplicar el mismo principio para simplificar este código y eliminar duplicidades extrayendo las porciones comunes a un filtro, resultando en algo así de bonito:

[Autoload(typeof(Friend))] // ¡Magia!
public class FriendsController: Controller
{
    public Task<IActionResult> View(Friend friend) 
    {
        ... // Prepare and show "View" view
    }

    public Task<IActionResult> Edit(Friend friend) 
    {
        ... // Prepare and show "Edit" view
    }

    public Task<IActionResult> Delete(Friend friend) 
    {
        ... // Prepare and show "Delete" view
    }
    ...
}
No sé lo útil que podrá resultar en la práctica pero, como mínimo, nos ayudará a conocer mejor cómo funciona por dentro el framework ASP.NET Core MVC.
lunes, 22 de octubre de 2018
Enlaces interesantes Después del parón de la semana pasada debido a compromisos profesionales (¡hola, chic*s!), continuamos con una nueva recopilación de enlaces que, como siempre, espero que os resulten interesantes :)

Por si te lo perdiste...

.NET / .NET Core

martes, 9 de octubre de 2018
Enlaces interesantes Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET / .NET Core

.NET timeline
martes, 2 de octubre de 2018
¿Qué podría salir mal? Pues como uno que os habla, seguro que muchos de vosotros habéis comparado miles de veces si un objeto es nulo utilizando un patrón de código C# como el siguiente:
var invoice = _invoiceRepository.GetById(18);
if(invoice == null) 
{
    // Hacer algo
}
¿Qué podría salir mal, verdad?

Pues aunque pueda parecer raro, hay casos en los que la comparación anterior no funcionaría bien... o mejor dicho, no funcionaría como esperamos.

Hace unos días leía un post de Khalid Abuhakmeh en el que hacía referencia a una charla de Channel 9 en la que Mads Torgersen recomendaba no utilizar la doble igualdad para comparar con null (minuto 33:00, aprox.)

lunes, 1 de octubre de 2018
Enlaces interesantes Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste:

.NET / .NET Core

martes, 25 de septiembre de 2018
ASP.NET Core MVC Hace unos días, un alumno del curso online de ASP.NET Core en CampusMVP (por cierto, desde hace unas semanas actualizado a la versión 2.1) me planteaba una cuestión que quizás podría interesar a alguien más, por lo que vamos a comentarla por aquí.

Básicamente, la duda era la siguiente:
¿Hay alguna forma sencilla de añadir el atributo [Authorize], pero sólo a los controladores que se encuentren en una carpeta determinada del proyecto, sin tener que aplicarlo uno a uno?
La respuesta rápida es: sí. Bueno, con matices ;) Incluso hay varias opciones, así que vamos a ver algunas de ellas, y de paso repasamos conceptos de ASP.NET Core MVC :)
lunes, 24 de septiembre de 2018
Enlaces interesantes Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste:

.NET / .NET Core

martes, 18 de septiembre de 2018
Tools Los que peinamos ya bastantes canas recordamos con nostalgia aquellas intensas sesiones de programación intentando arañar ciclos de CPU y bytes en nuestro flamante Spectrum para sacar el máximo provecho de, en el mejor de los casos, un Zilog Z80A a 3,5MHz con 48K de memoria RAM. ¡Ah, el maravilloso mundo de las micro-optimizaciones!

Hoy en día, salvo en contadas ocasiones, ha dejado de tener sentido invertir demasiado tiempo en estas labores. Tenemos máquinas potentes, con micros cuya velocidad se mide en GHz capaces de ejecutar bastantes tareas de forma concurrente, y muchos Gigabytes libres de memoria RAM en los que guardar información. Además, los frameworks actuales como .NET permiten despreocuparse de asuntos como la reserva o liberación de memoria porque ya hay sistemas de más bajo nivel que se encargan de eso por nosotros.

Indudablemente es un gran avance, pero esto ha llevado a que, con el tiempo, se nos esté atrofiando ese sentido arácnido que antes nos disparaba las alertas cuando cierto código podía ser optimizado para consumir menos recursos.

En la mayoría de escenarios, y sobre todo cuando trabajamos en entornos empresariales, aplicaciones de escritorio o webs de poca carga, está bien así. Sin embargo, es cierto también que las necesidades han cambiado.

Por ejemplo, ahora creamos frecuentemente aplicaciones mucho más complejas que pueden ser utilizadas a través de Internet por miles de usuarios de forma simultánea y todos ellos esperan respuestas rápidas. Estas aplicaciones se ejecutan en servidores cuyos recursos son compartidos entre todos los usuarios que pueden llegar a tener un coste importante y debemos exprimir al máximo. Aquí, y en otros escenarios similares, es donde aparece de nuevo la necesidad de introducir optimizaciones en el código.

En este post vamos a hacer una introducción al uso de BenchmarkDotNet, una magnífica herramienta que nos permitirá medir el rendimiento de nuestro código .NET para hacerlo más eficiente en términos de uso de procesador y memoria.

Pero antes de empezar, no olvidéis la famosa frase de Donald Knuth:
“Los programadores consumen una gran cantidad de tiempo pensando, o preocupándose, sobre la velocidad de partes no críticas de sus programas, y esos intentos de mejorar la eficiencia tienen posteriormente un gran impacto negativo sobre la facilidad de depuración o mantenimiento. Deberíamos olvidarnos de las pequeñas mejoras de eficiencia, digamos en un 97% de los casos: la optimización prematura es el origen de todos los males. Sin embargo, no debemos dejar pasar la oportunidad de mejorar ese crítico 3% restante”
lunes, 17 de septiembre de 2018
Enlaces interesantes ¡Hola de nuevo! Pues sí, tras una larga temporada de descanso, por fin estamos de vuelta, preparados para la nueva temporada y con las baterías cargadas al 99% (ese 1% me temo que es ya irrecuperable ;D)

Y para celebrarlo, nada mejor que un buen puñado de enlaces recopilados durante la semana pasada que, como siempre, espero que os resulten interesantes. :-)

.NET / .NET Core

jueves, 12 de julio de 2018
Pues eso, que parecía que no llegaba y las semanas se hacían cada vez más cuesta arriba, pero por fin es el momento de descansar un poco e intentar conseguir un merecido reinicio mental.

Durante las próximas semanas dejaré el blog a merced de las olas, pues estaré disfrutando con la familia en las maravillosas playas de Cádiz: sol, paseos, refrescantes bañitos en las aguas del Atlántico y chiringuitos playeros con aroma a pescado fresco. Un buen plan, sin duda ;)

Costa Ballena, Cádiz
Imagen original

Nos vemos a la vuelta, ya en el mes de septiembre, con la batería al 100% y listos para seguir buscando la variable ;)

¡Felices vacaciones a todos!

Publicado con ánimo vacacional en Variable not found.
martes, 10 de julio de 2018
ASP.NET Core MVCLos que lleváis tiempo programando APIs HTTP, ya sea con ASP.NET Core o con otras tecnologías, seguro que en muchas ocasiones habéis tenido que decidir cómo retornar al cliente, de forma más o menos normalizada, los errores producidos en el lado servidor.

Lo habitual es echar mano de los status code de HTTP para indicar problemas en el proceso de una petición; de hecho, este protocolo dispone de un rico conjunto de códigos que en principio parecen cubrir todas nuestras necesidades.

Pero no siempre es así. Por ejemplo, si tenemos un servicio que permite a los clientes de una empresa formalizar un pedido a través de un API y una llamada a este servicio retorna un error HTTP 403 (forbidden), claramente estamos indicando que el solicitante no tiene permisos para hacer un pedido. Sin embargo, no tenemos una forma clara de indicar cuál es la causa de esta prohibición (¿quizás las credenciales no son correctas? ¿o quizás el cliente no tiene crédito en la empresa? ¿o puede ser que el administrador lo haya denegado expresamente?)

Para aportar más detalles sobre el problema, normalmente necesitaremos retornar en el cuerpo de la respuesta información extra usando estructuras o formatos personalizados, probablemente distintos de una aplicación a otra, y documentarlos apropiadamente para que los clientes puedan entenderlos. Y aquí es donde entra en juego el estándar “Problem details”.
lunes, 9 de julio de 2018
Enlaces interesantes
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET / .NET Core

martes, 3 de julio de 2018
ASP.NET Core MVC Uno de los objetivos de ASP.NET Core ha sido siempre servir como infraestructura para la creación de servicios HTTP o APIs web, por lo que ya desde las primeras versiones se incluían funcionalidades específicamente diseñadas para facilitar esta tarea.

ASP.NET Core 2.1 continúa profundizando en esa línea e incluye entre sus novedades el nuevo atributo [ApiController], un decorador aplicable a controladores que los identifica como puntos de entrada de APIS, aplicando de forma automática una serie de convenciones bastante útiles a la hora de crear este tipo de componentes:
[ApiController]
[Route("api/[controller]")]
public class ValuesController : ControllerBase
{
    ...
}
Fijaos que, a diferencia de ASP.NET Web API (.NET Framework), se ha optado por utilizar un atributo en lugar de emplear herencia (en aquél framework existía la clase ApiController).
A continuación veremos qué debemos tener en cuenta a la hora de aplicar este atributo a nuestros controladores y qué convenciones son las que estaremos asumiendo al utilizarlo.
lunes, 2 de julio de 2018
MVP Award En esta ocasión sólo quería compartir con vosotros la gran alegría que supone ser honrado de nuevo con el galardón Microsoft MVP por las contribuciones y aportaciones realizadas a la comunidad de desarrolladores a lo largo del año pasado.

Son ya ocho años consecutivos y debería haberme acostumbrado a este subidón de primeros de julio, pero, como no suelo ser consciente de que ha llegado el día de los nombramientos, sigo recibiendo el conocido email de nombramiento casi con la misma emoción que aquella primera vez en que me pilló completamente desprevenido.

Muchas gracias a todos vosotros, amigos y amigas de Variable not found, porque si estoy aquí es porque me habéis regalado vuestro incondicional apoyo durante todos estos años.

Muchas gracias también al equipo del programa MVP en Microsoft y, en particular, a nuestra querida MVP lead Cristina González, por el gran trabajo que realizan.

Muchas gracias todos los que dedicáis vuestro tiempo la comunidad, seáis MVP o no, porque hacéis posible que todos aprendamos y mejoremos un poco más cada día.

Y, por supuesto, muchas gracias también a mi mujer e hijas, Inma, Inmita y María, porque ellas son las que permiten, con su infinita paciencia y comprensión, que pueda dedicar a mi pasión por el software más de lo que estrictamente requieren mis obligaciones profesionales.

Aprovecho también para enviar mi enhorabuena a los MVP renovados recientemente, y un caluroso abrazo de bienvenida a los que lo han sido por primera vez (es un momento muy bonito, ¡disfrutadlo!)

Sólo espero estar a la altura de esta distinción, compartida con gente de todo el mundo a la que admiro tanto personal como profesionalmente, y entre los que me enorgullezco de contar con grandes amigos. Y ahora, con esta dosis extra de motivación, ¡a seguir trabajando!

Desarrollador supermotivado
Source: Giphy

Publicado en Variable not found.
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.
lunes, 25 de junio de 2018
Enlaces interesantes
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET / .NET Core

martes, 19 de junio de 2018
ASP.NET Core MVC Como sabéis, por defecto las acciones MVC y Web API en ASP.NET Core retornan un IActionResult (o un Task<IActionResult> en caso de ser asíncronas). Este interfaz, cuya única misión es definir el método de ejecución asíncrona del resultado, ExecuteResultAsync(), es implementado por la gran variedad de tipos de resultado ofrecidos de serie por el framework, como ViewResult, RedirectResult o FileResult.

Sin embargo, no es esta la única opción disponible a la hora de especificar el resultado de una acción, como veremos a continuación.
lunes, 18 de junio de 2018
Enlaces interesantes
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET / .NET Core

martes, 12 de junio de 2018
ASP.NET Core Aparte de las novedades que comentamos hace una semana, ASP.NET Core 2.1 incluye algunas sorpresas adicionales que, sin ser revolucionarias, nos harán más sencillo el día a día. En esta ocasión vamos a comentar una característica introducida en .NET Core 2.1 que aporta mejoras de legibilidad en las trazas de excepciones producidas en llamadas asíncronas, algo que obtendremos for free, por el mero hecho de utilizar la última revisión del framework.

Veamos muy rápidamente en qué consiste.
lunes, 11 de junio de 2018
Enlaces interesantes Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET / .NET Core

martes, 5 de junio de 2018
ASP.NET CoreComo seguro sabréis, tras varias previews y release candidates, hace pocos días se lanzaron las actualizaciones de varios productos que ya llevábamos tiempo esperando:
Centrándonos en ASP.NET Core, la versión 2.1 incluye numerosas mejoras sobre su predecesora. Muchos componentes internos han sido reescritos y se han añadido características que, sin duda, continúan haciendo de ASP.NET Core un framework cada vez más completo y eficiente.

Pero eso sí, no rompe nada y todo lo que sabemos de ASP.NET Core 2.0 sigue siendo válido (de ahí que sea simplemente una revisión 2.x: no hay breaking changes).

En este post vamos a ver por encima las novedades que creo más destacadas de esta entrega.
lunes, 4 de junio de 2018
Enlaces interesantes Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET / .NET Core

martes, 29 de mayo de 2018
ASP.NET Core Hace algún tiempo hablamos por aquí sobre cómo implementar tareas en segundo plano en ASP.NET Core con IHostedService, una fórmula en principio bastante sencilla proporcionada por el framework para introducir en nuestras aplicaciones servicios, o procesos en segundo plano. Recordaréis que la magia consistía únicamente en implementar el interfaz IHostedService y registrar dicha implementación en el inyector de dependencias.

Sin embargo, aunque podía parecer lo contrario, la implementación correcta del interfaz IHostedService no era una tarea sencilla. De hecho, como se comenta en este issue de Github, IHostedService era un interfaz de muy bajo nivel y, al no quedar claro cómo debía utilizarse en escenarios reales, podría dar lugar a bastantes confusiones y problemas.
lunes, 28 de mayo de 2018
Enlaces interesantes Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET / .NET Core

martes, 22 de mayo de 2018
ASP.NET CoreRecordaréis que hace un par de semanas iniciamos un pequeño viaje en el que nuestro objetivo era renderizar una vista Razor de forma totalmente manual, desde procesos externos a ASP.NET Core y, por supuesto, introduciendo el menor número posible de dependencias hacia este framework. Ya comentamos entonces que este proceso consistía básicamente en:
  • Procesar la plantilla CSHTML y obtener código C# que permita renderizarla.
  • A continuación, compilar dicho código para obtener un componente ejecutable.
  • Por último, ejecutar el código para renderizar la plantilla.
En el primer post vimos cómo implementar el primero de los puntos, por lo que ahora nos centraremos en los siguientes, y conseguiremos el objetivo pretendido.

¡Seguimos! ;)
lunes, 21 de mayo de 2018
Enlaces interesantes Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET / .NET Core