Blazor ha venido en ASP.NET Core 8 cargadito de novedades, aunque probablemente la más destacable sea la introducción de las Blazor Web Apps como modelo de proyecto que unifica los distintos modos de renderizado de componentes. Aunque se trata de un cambio positivo, la realidad es que ha complicado algunas cosas que antes, con unos modelos de proyecto más sencillos, eran más fáciles de implementar.
Un ejemplo claro lo tenemos en las páginas de error 404 (not found): con este nuevo modelo unificado no hay una fórmula trivial o integrada de serie en el framework para implementar esta funcionalidad, tan habitual en nuestras aplicaciones.
En este post vamos a ver un posible enfoque para conseguir que si un usuario introduce una ruta inexistente en el navegador o bien pulsa un enlace interno que no exista, podamos mostrarle una página de error 404 totalmente personalizada, implementada como componente Blazor, e integrada en nuestra Blazor Web App.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- ¡No uses ToLower() o ToUpper() para comparar cadenas en C#!
José M. Aguilar - El archivo _ViewImports en ASP.NET Core MVC
José M. Aguilar
.NET Core / .NET
- Refactor your code with default lambda parameters
David Pine - Cancellation Tokens in C#
Rasheed K Mozaffar - When does the try, catch and finally blocks run in C#?
David Grace - Collection Performance: Introducing FrozenSet in .NET 8: Benefits and Benchmark PerformanceCollection Performance
David McCarter - Privacy and security improvements in .NET modernization tooling
Mike Rousos - How to Cast an Int to an Enum in C#
Chris Pietschmann - Exploring the generated code: List<T> and fallback cases
Andrew Lock - How to Ignore a Property in AutoMapper
Żaneta Borowska - C#: Read Text and JSON File Contents into Variable in Memory
Chris Pietschmann - How to Use FakeLogger to Test Logging Code in .NET
Osman Sokuoglu - How to Use C# to Properly Follow OAuth Authentication Flows
Peter Smulovics - C# 13 params collections
NDepend Team - What Does the null! Statement Do?
Januarius Njoku - Announcing Third Party API and Package Map Support for .NET Upgrade Assistant
Marco Goertz - The Best Way To Map Objects in .Net in 2024
Anton Martyniuk
Llevamos ya varias entregas de la serie C# bizarro, donde, como sabéis, ponemos a prueba nuestros conocimientos de C# llevando al extremo el uso de algunas de sus características, lo que de paso nos ayuda a conocer mejor aún el lenguaje.
Hoy vamos a proponer un nuevo reto, mostrando un comportamiento que quizás muchos conozcáis, pero seguro que otros nunca habéis tenido ocasión de verlo. A ver qué tal se os da ;)
Observad atentamente esta sencilla aplicación de consola:
int i = 1;
int accum = 0;
while (i <= 5)
{
accum += i;
Debug.WriteLine($"Adding {i++}, Accumulated = {accum}");
}
Console.WriteLine($"Total: {accum}");
A la vista del código, las preguntas son dos: ¿Qué resultado obtenemos al ejecutar la aplicación? ¿Será siempre así?
Obviamente, tiene algo de truco, pero si lo pensáis un poco seguro que podéis responder a las preguntas. Y si no, pulsad aquí para ver la solución; 👇👇
En principio, lo lógico es pensar que deberíamos ver en el canal de depuración (la ventana Output>Debug en Visual Studio) el valor actual y el total acumulado en cada iteración, lo que nos permite ir siguiendo en detalle el funcionamiento interno:
Adding 1, Accumulated = 1
Adding 2, Accumulated = 3
Adding 3, Accumulated = 6
Adding 4, Accumulated = 10
Adding 5, Accumulated = 15
Finalmente, se mostrará por consola el valor definitivo:
Total: 15
Esto será justamente lo que obtengamos si copiamos el código en Visual Studio y lo ejecutamos pulsando F5 o el botón correspondiente del IDE. Hasta ahí, perfecto ;)
Sin embargo, este código tiene una trampa oculta. Si desde Visual Studio cambiamos el modo de compilación a "Release" y lo lanzamos, o bien si lanzamos directamente el ejecutable que encontraremos en la carpeta bin/Release/net8.0
(o la versión de .NET que uses, da igual), veremos que la aplicación no se detiene nunca (?!)
El motivo de este extraño comportamiento lo explicamos hace ya bastantes años por aquí, en el post métodos condicionales en C#.
Estos métodos, presentes desde las primeras versiones de .NET (pre-Core), se decoran con el atributo [Conditional]
para hacer que éstos y todas las referencias a los mismos sean eliminadas del ensamblado resultante de la compilación si no existe una constante de compilación determinada.
De hecho, si acudimos al código fuente de la clase estática Debug
, veremos que su método WriteLine()
está definido de la siguiente manera:
public static partial class Debug
{
...
[Conditional("DEBUG")]
public static void WriteLine(string? message)
=> s_provider.WriteLine(message);
}
Cuando compilamos en modo depuración, la constante DEBUG
estará definida, por lo que este método podrá ser invocado con normalidad y todo funcionará bien. Sin embargo, si compilamos en Release o cualquier otra configuración que no incluya la constante, este método desaparecerá del ensamblado, junto con las referencias que lo utilicen.
Es decir, si usamos el modo Release, el código que hemos escrito antes quedará tras la compilación como el siguiente:
int i = 1;
int accum = 0;
while (i <= 5)
{
accum += i;
// La siguiente llamada será eliminada en compilación:
// Debug.WriteLine($"Adding {i++}, Accumulated = {accum}");
}
Console.WriteLine($"Total: {accum}");
Fijaos que, al eliminar la llamada, con ella desaparecerá también la expresión de autoincremento del índice del bucle i++
, por lo que nunca se alcanzará la condición de salida y quedará iterando de forma indefinida.
Bonito, ¿eh? ;)
Publicado en Variable not found.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- El nuevo modificador "file" de C# 11: tipos visibles exclusivamente en el archivo en el que se definen
José M. Aguilar - La carpeta wwwroot en ASP.NET Core
José M. Aguilar
.NET Core / .NET
- Retrying Failed HttpClient Requests in .NET Using Polly
Gergő Vándor - Does an HttpClient await the Header and the body?
Steven Giesel - Frozen Collections in .NET 8
Sharmila Subbiah - How to Use the LINQ ToDictionary Method in C#
Januarius Njoku - Introducing collection expressions in C#12
Andrew Lock - Differences Between Span and Memory in C#
Bozo Spoljaric - 5 Practical Ways to Add Polly to Your C# Application
Metalama Team - C# Array and List Fastest Loop in 2024
NDepend Team - Weak Events in C#
Satya Prakash - What’s New in C# 13 for Developers?
Vinoth Kumar Sundara Moorthy - C# Version String Formatting
Rick Strahl - Weak Events in C#
Satya Prakash - Creating Custom Attributes in C#
Anton Martyniuk
Este post pertenece a una serie de tres partes donde estamos viendo cómo renderizar componentes Blazor en el interior de vistas MVC de ASP.NET Core. Hasta ahora, hemos visto cómo renderizar desde vistas MVC componentes Blazor usando los siguientes modos de renderización:
En esta entrega final veremos cómo renderizar componentes Blazor ejecutados por completo en el lado cliente (WebAssembly).
Este post pertenece a una serie de tres partes donde estamos viendo cómo renderizar componentes Blazor en vistas MVC de ASP.NET Core.
En la primera parte de la serie vimos cómo renderizar componentes estáticos (SSR) en servidor, y ahora vamos a centrarnos en hacerlo con componentes con interactividad también en el lado servidor (Blazor Server), dejando para una siguiente entrega los componentes interactivos ejecutados por completo en cliente con WebAssembly.
Publicado por José M. Aguilar a las 8:05 a. m.
Etiquetas: aspnetcoremvc, blazor, blazorserver, trucos
Hace no demasiado, mientras analizábamos la posibilidad de que Blazor acabara en algún momento sustituyendo a MVC como tecnología "por defecto" para el desarrollo de aplicaciones web en .NET, comentaba que técnicamente no hay nada que impida a ambas tecnologías convivir pacíficamente en una misma aplicación. De hecho, están diseñadas para trabajar juntas :)
En este sentido, uno de los escenarios soportados es la inserción de componentes Blazor en el interior de vistas de una aplicación ASP.NET Core MVC. Esto puede ser muy interesante, entre otros casos, si queremos ir introduciendo Blazor progresivamente en aplicaciones MVC existentes o para reutilizar componentes entre distintos proyectos.
En esta miniserie vamos a ver cómo conseguirlo con los distintos modos de renderizado de Blazor, porque cada uno tiene sus particularidades:
- Renderizado estático (SSR), lo que veremos en este post.
- Renderizado en servidor (Blazor Server), en un futuro post.
- Renderizado en cliente (Blazor WebAssembly), también en un artículo posterior.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- ¿Cómo se llama el operador "-->" de C#?
José M. Aguilar - ¿Se pueden lanzar dos aplicaciones ASP.NET Core desde el mismo host?
José M. Aguilar
.NET Core / .NET
- Top 10 C# Recent Improvements
NDepend Team - How to Print a 2D Array to the Console in C#
Ellie Zubrowski - How to use C# async/await for API calls & to stop blocking
David Grace - Refactor your code using alias any type
David Pine - MSTest 3.4 is here with WinUI support and new analyzers!
Amaury Levé & Marco Rossignoli - State Machines, Light Switches, and Space Travel with Stateless and .NET 8
Khalid Abuhakmeh - Fast and Compact Structured Logging in C# Using String Interpolation
Metalama team - Automate your .NET SDK updates for consistent and reproducible builds with global.json and Renovate
Anthony Simmon - StringBuilders magic for very large strings
Steven Giesel - .NET Core–Check if console app is running with administrative privileges
Bart Wullems - New And Proposed Changes For C# 13
Peter Ritchie - Bouncy Castle Cryptography Library for .NET
Alvaro Montoya - Async Await Mastery: Handling Exceptions Like a Pro in C#
Kons Fedorov - IDisposable: What Your Mother Never Told You About Resource Deallocation
Stephen Cleary - How To Write Elegant Code with C# Switch Expressions
Anton Martyniuk
El espacio de nombres System.IO
de .NET proporciona clases para trabajar con archivos y directorios, algo que, a priori, no tendría demasiado sentido en componentes Blazor WebAssembly, ya que éstos se ejecutan en el navegador del cliente y, por motivos de seguridad, no tienen acceso al sistema de archivos del servidor, ni tampoco a los archivos del dispositivo del usuario que está ejecutando la aplicación.
El primero de los casos es salvable: si desde un componente Blazor WebAssembly quisiéramos leer o escribir archivos en el servidor, podríamos hacerlo a través de una API que, ejecutada en el servidor, tuviera acceso a este tipo de recursos.
Sin embargo, técnicamente no hay forma de acceder a los archivos locales del usuario, dado que los componentes Blazor WebAssembly se ejecutan en el sandbox del navegador, que impide acceder a los recursos del sistema.
Pues bien, a pesar de ello, y de forma totalmente contraria a lo que podríamos intuir, desde Blazor WebAssembly sí que se pueden usar los componentes de System.IO
(bueno, o muchos de ellos) para leer o escribir archivos y directorios, aunque con algunas peculiaridades que veremos a continuación.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Personalizar restricciones de ruta en línea en ASP.NET Core
José M. Aguilar - Inyección de dependencias en filtros ASP.NET Core MVC
José M. Aguilar
.NET Core / .NET
- ¿.NET 7 no soportado, pero .NET 6 sí? - Cómo funcionan las versiones en .NET
José Manuel Alarcón - .NET Workloads 101
Miguel Angel Martín Hernández - Introducing links to source code for .NET API Docs
Min Huang - How to test a Roslyn analyzer
Gérald Barré - How to Compare Two Dictionaries in C#
Januarius Njoku - Blocking primary constructor member capture using a Roslyn Analyzer
Andrew Lock - Fastest Ways to Perform Base 10 Conversions in C#
Martin Chege - What's New in C# 13: Enhanced Params, Performance Boosts, and New Extension Types
Almir Vuk - .NET Core Configuration in .NET 8
Dhananjeyan Balaretnaraja - Introduction to the StronglyTypedId Package in .NET
Caleb Okechukwu - Running a Hosted Service in a Console Application
Bryan Hogan - Cancel WhenAny - linked CancellationTokenSource
Steven Giesel - Metadata Consulting [dot] ca: C# dotNet The fastest way to check if a file is a PDF file or not
Metadata Consulting - Lookup in C#
Januarius Njoku - ASP.NET Core Basics: Getting Started with GraphQL
Assis Zang - Using thread-safe classes doesn’t make your code thread-safe
Henrique Dalcin Dalmas - How to Set the Exit Code for a Console Application in .NET
Stefan Cruz