Si nos dedicásemos a enroscar tapones de botellas probablemente podríamos medir nuestra productividad en términos del número de botellas cerradas por hora. Si cargásemos sacos en un muelle, quizás en kilos transportados por jornada... Hay muchos trabajos en los que es relativamente sencillo establecer una medida para conocer el grado de productividad con el que desempeñamos nuestras obligaciones.
Lamentablemente, esto no es así en la industria del software, que durante años ha ido dando tumbos, probando y descartando sucesivamente diversas métricas para intentar medir la productividad de los desarrolladores, como el cómputo de líneas de código por día, puntos función, puntos de historia o el grado de completitud de sprints, pero siempre sin éxito. En el desarrollo de software todo es demasiado etéreo: dado que no creamos ni manipulamos productos tangibles, no hay nada que poder pesar o contar, salvo las horas pegados a nuestra silla.
Sin embargo, todos tenemos una idea intuitiva de lo que es un desarrollador productivo, e incluso se ha hablado bastante de los desarrolladores 10x: programadores que son al menos diez veces más productivos que los que se encuentran en el lado opuesto del espectro. Esta idea parte de estudios científicos contrastados, y algunos destacados gurús incluso suben la apuesta llegando a estimar que determinados desarrolladores pueden producir entre diez y veintiocho veces más que sus compañeros. Casi nada.
Sin duda, un desarrollador 10x es todo un lujazo para las empresas, que lucharán para atraerlos, normalmente a base de ofrecer unas condiciones espectaculares, porque es mucho más rentable ofrecer a un desarrollador 10x el triple de sueldo que tener a diez desarrolladores para conseguir el mismo resultado.
Nuestro objetivo profesional, por tanto, debería ser dar el salto y convertirnos en uno de ellos.
Publicado por José M. Aguilar a las 12:01 a. m.
Etiquetas: 10x, bootcamp, inocentadas, productividad
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- ¿Dónde está Server.MapPath() en ASP.NET Core?
José María Aguilar - Cómo mostrar el número de usuarios conectados a una aplicación Blazor Server, en tiempo real
José María Aguilar
.NET Core / .NET
- Mejorar la legibilidad de números en tu código C# con separadores de dígitos
José Manuel Alarcón - What's next for System.Text.Json?
Layomi Akinrinade - Building a Code Analyzer for .NET
Tim Heuer - Batch.Parallel
Marc Clifton - C# in Simple Terms - Indexers
Matthew Jones - Implementing a Text Templating Language and Engine for .NET
Alexandre Mutel - Thinking With Properties: Examining Where
Cameron Presley - Implementing the page object pattern in UI tests
James Croft - Never forget a #if when multi-targeting .NET libraries or applications
Gérald Barré - Creating a game art asset pipeline in .NET
Sam Eddy - From .NET Standard to .NET 5
Immo Landwerth - How to add User-Agent header to HttpClient in .NET
Kristoffer Strube - .NET 5.0 on Google Cloud
Mete Atamel - Playing with C#9 Top-level Programs, Records and Elasticsearch.NET - Steve Gordon
Steve Gordon - The proper usages of Exceptions in C#
Patrick Smacchia - Overloading Vs. Overriding in C#
Sam Walpole - .NET 5 Source Generators - MediatR - CQRS
Tore Nestenius - C# vs. F#
Urs Enzler - C# 9 Covariant Return Types
Khalid Abuhakmeh
En Blazor, es habitual implementar la interfaz de nuestros componentes de forma declarativa, mezclando etiquetas que:
- Pueden ser HTML, y cuyo resultado irá textualmente al navegador
- Pueden ser instancias de otros componentes, por lo que al navegador irá el resultado de la renderización de éstos.
Por ejemplo, el siguiente código envía al navegador la etiqueta <h1>
y luego el resultado de renderizar el componente Blazor <MyComponent>
, en cuyo interior podrán existir a su vez otras etiquetas o componentes:
@page "/home"
<h1>Welcome!<h1>
<MyComponent />
Fijaos que, aunque es la fórmula que emplearemos en la mayoría de ocasiones, es una estructura totalmente rígida: podemos tener la total certeza de que el componente que será instanciado en la página anterior es MyComponent
, pero, ¿qué ocurre si queremos poder decidir en tiempo de ejecución qué componente instanciaremos en la página?
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- ¿Dónde están Application_Start y Application_End en ASP.NET Core?
José María Aguilar - Capturar todos los parámetros enviados a un componente Blazor
José María Aguilar
.NET Core / .NET
- Programación mínima, C# vs Python
Sergio León - Null Checking en C#
Jorge Serrano - What's new in Windows Forms runtime in .NET 5.0
Igor Velikorossov - .NET December 2020 Updates – 5.0.1
Rahul Bhandari - Rethrowing your exceptions wrong in .NET could erase your stacktrace
Niels Swimberghe - C# 9 records as strongly-typed ids
Thomas Levesque - Common Use Cases For .NET Reflection
Khalid Abuhakmeh - Cryptography Improvements in .NET 5
Tomasz Pęczek - Bring lights in Unity into the real-world using Philips Hue
Paul Marsh - New in .NET 5 - Top-level Statements
Bradley Wells - Automate a Markdown links page with Pinboard and C#
Dave Brock - Add Configuration to a .Net Core Console Application
Paul Michaels - C# in Simple Terms - Dates and Times
Matthew Jones - Using .NET and PowerPoint to generate cover images
Gérald Barré - No recompile, no redeploy, managing features flags in .NET Core, locally and with Azure
Chris Noring - Producing Packages with Source Link
Claire Novotny - Use local function attributes with C# 9
Dave Brock - The proper usages of the keyword 'static' in C#
Patrick Smacchia - Making C# More Welcoming
Matt Eland - Simplifying Multithreaded Scenarios With PostSharp Threading
Wade Gausden - C# 9 Records and Init Only Settings Without .NET 5
Brant Burnett - Dynamic Class Creation in C# - Preserving Type Safety in C# with Roslyn
José Manuel Redondo López
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Retorno de referencias y referencias locales en C#
José María Aguilar - Mostrar HTML "crudo" en componentes Blazor
José María Aguilar
.NET Core / .NET
- Introducing WaveEngine 3.1 based on .NET 5
Javier Cantón Ferrero - C# In Simple Terms - String Manipulation and Cultures
Matthew Jones - Noisy logs? Improve your signal-to-noise ratio with per-request logging and sampling
Gael Fraiteur - .NET 5 Breaking Changes to the Base Class Library
Jonathan Allen - Investigating a performance issue with a regex
Gérald Barré - Should You Always Create a Nuget Package? Asking for a Friend...
Shawn Wildermuth - When C# 9.0 patterns go wrong: mechanism over intent
Ian Griffiths - .NET Core 2.1, 3.1, and .NET 5.0 updates are coming to Microsoft Update
Jamshed Damkewala - .NET 5 Breaking Changes: Historic Technologies
Jonathan Allen - C# 9 - Top-Level Statements & C# 8 - Switch Expressions
Claudio Bernasconi - Understand The .NET 5 Runtime Environment
Khalid Abuhakmeh
Una pequeña pero interesante novedad introducida en Blazor 5, es la posibilidad de escribir nuestras propias factorías de componentes, o, como les llaman en el framework, Component Activators.
El Component Activator es un objeto singleton que implementa la interfaz IComponentActivator
, cuyo único requisito es el cumplimiento del siguiente contrato:
public interface IComponentActivator
{
IComponent CreateInstance(Type componentType);
}
Como se puede intuir, Blazor invocará al activator registrado en el sistema justo en el momento en que va a instanciar un componente: se le suministra el tipo como parámetro, y retornará ya un objeto IComponent
, la interfaz más básica que cumplen todos los componentes Blazor.
Por defecto, se utiliza como activador la clase interna DefaultComponentActivator
:
internal class DefaultComponentActivator : IComponentActivator
{
public static IComponentActivator Instance { get; } = new DefaultComponentActivator();
public IComponent CreateInstance(Type componentType)
{
var instance = Activator.CreateInstance(componentType);
if (!(instance is IComponent component))
{
throw new ArgumentException($"The type {componentType.FullName}"
+ $"does not implement {nameof(IComponent)}.", nameof(componentType));
}
return component;
}
}
Obviamente, si quisiéramos intervenir en el proceso de construcción de componentes, sólo tendremos que implementar nuestra clase personalizada y registrarla como singleton en el inyector de dependencias, asociada a la interfaz IComponentActivator
.
Para crear nuestra propia implementación, fijaos que la clase DefaultComponentActivator
es interna y no podemos heredar de ella, pero tiene un código tan simple que podemos usarlo para crear nuestras propias versiones.
Veamos un par de ejemplos.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Literales binarios y separador de dígitos numéricos en C#7
José María Aguilar - Blazor Server + Entity Framework Core = InvalidOperationException (si no tienes cuidado)
José María Aguilar
.NET Core / .NET
- Announcing Microsoft Q&A for .NET
James Montemagno - .NET Conf 2020 Demos & Sessions for .NET 5 + Virtual Events!
Jayme Singleton - Optimizing CSharp Null-Coalescing Operator
Stéphane Gay - How to make a WinForms app with .NET 5 entirely from the command line and publish as one self-contained file
Scott Hanselman - C# 9 - Improving performance using the SkipLocalsInit attribute
Gérald Barré - Conventional Options
Derek Greer - .Net 5 is PERFECT for DevOps
Davide Benvegnù - C# In Simple Terms - Expressions, Lambdas, and Delegates
Matthew Jones - Spectre.Console lets you make beautiful console apps with .NET Core
Scott Hanselman - C# 9 Records as DDD Value Objects
Vladimir Khorikov - Astonishing Performance of .NET 5: More Data
Alex Yakunin - Tests are hard, LightBDD can help
Jon Hilton - Monitoring .NET scheduled tasks
Thomas Ardal - Upgrading several of my Applications and Libraries to .NET 5.0
Rick Strahl - Using C#9 record and init property in your .NET Framework 4.x, .NET Standard and .NET Core projects
Patrick Smacchia - The difference between overloading and overriding in C#
Sam Walpole - The updated GetGCMemoryInfo API in .NET 5.0 and how it can help you
Maoni Stephens
Hace unos días fue lanzada la nueva versión de ASP.NET Core basada en el flamante .NET 5, que incluye un buen número de novedades para los desarrolladores Blazor, algunas de ellas bastante jugosas.
En este post vamos a ver por encima las que creo que son más destacables en esta nueva entrega:
- .NET 5 y mejoras de rendimiento
- CSS Isolation
- JavaScript Isolation
- Virtualización
- InputRadio & InputRadioGroup
- Soporte para IAsyncDisposable
- Soporte para upload de archivos
- Control del foco
- Parámetros de ruta catch-all
- Protected browser storage
- Prerenderización WebAssembly
- Lazy loading de áreas de aplicación en Web Assembly
- Otros cambios y mejoras
Publicado por José M. Aguilar a las 10:13 a. m.
Etiquetas: blazor, blazorserver, blazorwasm, novedades
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Diez años de enlaces interesantes: lo que siempre habéis querido saber sobre esta serie
José María Aguilar - Deconstrucción de tuplas y clases en C# 7
José María Aguilar
.NET Core / .NET
- dotnet-script 1.0.0 released – with support for .NET 5.0 and C# 9
Filip Woj - .NET Conf 2020 and .NET 5 links
João Antunes - .NET 5 and .NET Core SDK version pinning
Feodor Fitsner - Migrate .NET Core 3.1 to .NET Core 5.0
John Smith - C# in Simple Terms: Tuples and Anonymous Types & Attributes and Reflection
Matthew Jones - Creating a Network Speed Monitor in C#
Hannes Du Preez - Process.WaitForExitAsync is not the async equivalent of Process.WaitForExit in .NET 5
Gérald Barré - C# Index and Range Operators Explained
Patrick Smacchia - Coding Faster with the dotNetTips Utility: November 2020 Update
David McCarter - Your dotnet outdated is outdated! Update and help keep your .NET projects up to date
Scott Hanselman - Simplify your ASP.NET Core API models with C# 9 records
Dave Brock - Lazy Sunday with .NET 5
Shawn Wildermuth - C# Expression Trees: Property Getters
Zanid Haytam - Recursive Fibonacci and Memoization in C#
David Hayden - Vertical Slice Example Updated to .NET 5
Jimmy Bogard - What is .NET 5? (Overview, Features, Performance, Download)
Damir Arh - 6 less popular facts about C# 9 records
Konrad Kokosa - Understanding Disposables In .NET Dependency Injection Part 1 & Part 2 & Part 3
Steve Collins
Un alumno del curso de Blazor que tutorizo en CampusMVP me exponía problema bastante curioso con el que se había topado al implementar una página que, simplificando el escenario, venía a ser como la siguiente:
@page "/sum/{a:decimal}/{b:decimal}"
<h1>The sum is: @(A+B)</h1>
@code {
[Parameter] public decimal A { get; set; }
[Parameter] public decimal B { get; set; }
}
Esta página funcionaba correctamente con números enteros: podíamos acceder a "/sum/1/2" y veíamos el resultado correcto ("The sum is: 3"). Esto era así tanto accediendo a través del sistema de routing de Blazor (es decir, usando un link hacia esa ruta desde dentro de la aplicación) como accediendo directamente a la página introduciendo la ruta en la barra de direcciones del navegador.
Sin embargo, el problema surgía al usar valores decimales. Si desde dentro de la aplicación pulsábamos un enlace hacia "/sum/1.1/2.2", el resultado obtenido era correcto ("The sum is: 3.3"). Sin embargo, si en ese momento refrescábamos esa página, o bien accedíamos directamente a ella introduciendo la URL en el navegador, el servidor retornaba un error 404.
Extraño, ¿no?
Ahí van los enlaces recopilados durante la semana pasada, con jugosas novedades procedentes de la .NET Conf 2020. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Expresiones throw en C# 7
José María Aguilar - AddMvc(), AddControllers(), AddControllersWithViews(), AddRazorPages()... ¿qué es todo eso?
José María Aguilar
.NET Core / .NET
- Announcing .NET 5.0
Richard Lander - C# 9.0 on the record
Mads Torgersen - Announcing C#/WinRT Version 1.0 with the .NET 5 GA Release
Angela Zhang - Announcing F#5
Phillip Carter - Getting Started With NuGet 5.8
Jon Douglas - C# 9: Record Types Introduction & Deep-Dive
Claudio Bernasconi - .NET 5 - The breaking changes you need to know about
Miguel Bernard - Five Questions You May Have About ASP.NET Core For .NET 5
David Grace - Should I Migrate to .NET 5?
Rockford Lhotka - Astonishing Performance of .NET 5
Alex Yakunin - C# in Simple Terms: LINQ basics & Generics
Matthew Jones - C# ways of handling when being throttled by an API
Dominique St-Amand - Generating Code in C#
Rocket Mortgage Technology - Back to C# basics: Difference between "=>" and "{ get; } =" for properties
Jiří Činčura - Best 5 Tools for .NET Monitoring
Iryne Somera - Migrating to the new C# Azure KeyVault SDK Libraries
Dominique St-Amand
Por si te lo perdiste...
- Tuplas en C# 7
José María Aguilar - Cómo implementar view-models de componentes Blazor en clases code-behind
José María Aguilar
.NET Core / .NET
- Procesar SIGTSTP en netcore (Linux)
Eduard Tomás - Introducing C# 9: Extension GetEnumerator support for foreach loops
Anthony Giretti - C# in Simple Terms: Exceptions and Exception Handling & Arrays and Collections
Matthew Jones - Async code smells and how to track them down with analyzers
Cezary Piątek - .NET Core with NGINX on Linux
Irina Scurtu - Looking At System.IO.Path
Khalid Abuhakmeh - C#9 - init-only properties are not read-only at runtime
Gérald Barré - Additional HTTP, Sockets, DNS and TLS Telemetry in .NET 5 - Steve Gordon
Steve Gordon - New Environment.ProcessId in .NET 5
Jiří Činčura - Module Initializers In C# 9
Khalid Abuhakmeh
Durante las entregas anteriores hemos estado comentando los códigos de estado HTTP coincidentes con la entrega de enlaces interesantes de la semana, por aquello de tener culturilla general. En esta ocasión le llegó el turno al HTTP 419, que simplemente no existe, por lo que omitiremos esta sección hasta volvamos a coincidir de nuevo ;)
Y dicho esto, ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :)
Por si te lo perdiste...
- Desinstala fácilmente versiones antiguas de .NET Core con "dotnet-core-uninstall"
José María Aguilar - Ordenar por un campo enum con WebGrid
José María Aguilar
.NET Core / .NET
- The Future of Desktop: All You Need to Know about .NET 5!
Bianka Banova - Template-based code generation with Razor and Roslyn
Matteo Prosperi - Enumerating files using Globbing and System.IO.Enumeration
Gérald Barré - C# in Simple Terms: Interfaces and Abstract Classes & Namespaces
Matthew Jones - Mind Your Strings with .NET 5.0
Jimmy Bogard - FormattableStringFactory and Formats
Khalid Abuhakmeh - C# 9 The unknown goodies
Miguel Bernard - Consuming JSON Objects Stream (NDJSON) With HttpClient
Tomasz Pęczek - Generate QR Codes With C#
Khalid Abuhakmeh - Intercepting methods with PostSharp Community
Petr H. - Using C# 9 records as strongly-typed ids
Thomas Levesque
Hace unos días, un alumno de mi curso de Blazor en CampusMVP me preguntaba sobre la posibilidad de detectar cuándo un componente se estaba procesando en "modo prerenderización", con el fin de ejecutar cierta lógica únicamente en ese caso.
Me habría gustado responderle algo como "usa la propiedad IsPrerendering
del componente y ya lo tienes". Pero no, las cosas no son tan sencillas; Blazor no proporciona ninguna propiedad del estilo, y no existen fórmulas directas para conseguirlas, más allá de un par de hacks bastante poco elegantes:
- Intentar acceder al contexto HTTP, sólo disponible cuando estamos ejecutando código en el interior de una petición (es decir, cuando el componente se está prerenderizando).
- Ejecutar una función Javascript mediante interop, y capturar la excepción que se produce al hacerlo mientras se está prerenderizando el resultado, pues durante este proceso no es posible utilizar los mecanismos de interoperación.
En este post vamos a ver una alternativa más apropiada que las anteriores, sacando partido al inyector de dependencias y al hecho de que la prerenderización se ejecuta en el propio proceso de la petición que carga la página inicialmente. Y como veréis, la idea es muy sencilla.
Je, estaba deseando llegar a esta entrega de enlaces para poder contaros algo acerca del código de estado HTTP 418 😊
HTTP 418, cuya reason phrase es "I'm a teapot" (soy una tetera), es un código de estado definido por la IETF para dar soporte al HTCPCP (Hyper Text Coffe Pot Control Protocol), un protocolo especificado oficialmente en la RFC 2324 en el año 1998, con el objetivo de definir las normas de comunicación para posibilitar el control, la monitorización y el diagnóstico de cafeteras a través de Internet.
El protocolo, basado en HTTP, establece nuevos verbos (como BREW, para iniciar la elaboración de café), media types, encabezados personalizados e incluso un nuevo esquema de URIs llamado coffee URI scheme que puede utilizarse para identificar servidores y tipologías de café usando una sintaxis estándar.
Y también define nuevos códigos de retorno. Concretamente, el error 418 es usado por el servidor (el dispositivo, en este caso) para indicar al cliente que no puede procesar la petición al tratarse de una tetera y no una cafetera. Un error de cliente 4xx en toda regla ;)
Obviamente esto no era real, se trató de una trabajada broma del April's Fools Day (algo similar a nuestro Día de los Inocentes), pero que ha perdurado como una anécdota curiosa y simpática en el frío mundo de la definición de estándares.
Y ahora, van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- ¿Usar try/catch es malo para el rendimiento? Spoiler: no, siempre que nada falle
José María Aguilar - Inline out variables en C# 7
José María Aguilar
.NET Core / .NET
- Lecciones aprendidas tras migrar más de 25 proyectos a .NET Core
CampusMVP - Async code smells and how to track them down with analyzers
Cezary Piątek - Introducing C# 9: Attributes on local functions
Anthony Giretti - Abstract Classes vs. Interfaces in C#
Jeremy Clark - Choose a .NET Game Engine
Abdullah Hamed - Extract Available Settings Using C#
Zanid Haytam - C# in Simple Terms - Structs and Enums & Inheritance and Polymorphism
Matthew Jones - Dynamically invoking a generic method with Reflection in .NET C#
Brian Lagunas - Introducing C# 9: Static anonymous functions
Anthony Giretti - A Highly Biased Review of C# Changes from Version 1.0 to 9.0
Matthew MacDonald - C# designer Torgersen: Why the programming language is still so popular and where it's going next
Owen Hughes - C# 8.0 nullable references: defeating the point with empty strings
Ian Griffiths - C# 9 Record Factories
Steve Collins - DICOM Image Viewer
Amarnath S
Todos los usuarios que están utilizando una aplicación Blazor Server mantienen una conexión abierta con el servidor para enviar eventos y recibir las modificaciones de la interfaz de usuario. Y si habéis trabajado algo con Blazor, sabréis que cuando dicha conexión se corta aparece en el navegador un mensaje como el mostrado en la siguiente captura de pantalla:
Como se puede ver en la captura anterior, cuando se detecta la desconexión, se añade automáticamente a la página un <div>
con el identificador components-reconnect-modal
que bloquea la página (observad su posición fija a pantalla completa), mostrando al usuario un mensaje informándole de que se está intentando reconectar.
Si, transcurridos algo más de 30 segundos, la reconexión no ha sido posible, el contenido del <div>
cambiará para informar al usuario de que la conexión no pudo ser restablecida, y ofreciendo un botón para reintentarlo y un enlace para recargar la página completa:
Podemos comprobar muy fácilmente estos comportamientos si lanzamos la aplicación sin depuración (Ctrl+F5) desde Visual Studio y detenemos IIS Express desde su icono en la barra de herramientas de Windows.
Como comportamiento por defecto la verdad es que no está nada mal, pues nos proporciona una solución out of the box que será suficiente la mayoría de los casos. Sin embargo, la estética es obviamente mejorable... ¿y si quisiéramos modificar visualmente estos mensajes o incluso su comportamiento? Pues es lo que veremos en este post 🙂
expect
de la petición.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes y, por supuesto, que vuestras expectativas queden satisfechas :-)
Por si te lo perdiste...
- Tip: desinstalar rápidamente paquetes NuGet en proyectos .NET Core
José María Aguilar - Cambiar el idioma de mensajes del SDK de .NET Core
José María Aguilar
.NET Core / .NET
- Cómo garantizar el soporte a largo plazo de tu aplicación .NET
CampusMVP - Mediator Pattern en C#
Jorge Serrano - ¿Cómo puedo probar .NET 5 y C# 9?
Jorge Serrano - Announcing .NET 5.0 RC 2
Richard Lander - Introducing .NET Live TV - Daily Developer Live Streams
James Montemagno - How to Debug C# 9 Source Code Generators
Nick Randolph - Web Scraping with C#
Pierre de Wulf - Export Bitly Links using C#
Jason Gaylord - C# 9: Partial Methods get more flexibility
Miguel Bernard - Dynamic Queries with Expressions Trees in C#
Michael Shpilt - Async code smells and how to track them down with analyzers
Cezary Piątek - Some helpful extensions when dealing with types in .NET |
Marco Siccardi - C# 8.0 nullable references: prepare today by not misusing 'as'
Ian Griffiths - 4 Awesome Tools for .NET Debugging in Production
Michael Shpilt - C# in Simple Terms - Methods, Parameters, and Arguments & Classes and Members
Matthew Jones - Scaling Hangfire: Process More Jobs Concurrently
Derek Comartin - Ace Switch Expressions in C# 8
Khalid Abuhakmeh - .NET Internals: System.Threading.Channels - UnboundedChannel<T> Part 3 - Steve Gordon
Steve Gordon - Classic Path.DirectorySeparatorChar gotchas when moving from .NET Core on Windows to Linux
Scott Hanselman - How to Upgrade .NET CLI Templates
Kevin W. Griffin
Hoy le toca el turno a un código de estado HTTP que no es nada habitual: HTTP 416 (Range Not Satisfiable). Este resultado se obtiene cuando la solicitud de un rango, especificado en el encabezado Range
, indica un valor que no puede ser satisfecho por el servidor, quizás porque son inválidos o porque superan el tamaño del recurso.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Rutado dinámico en ASP.NET Core 3 MVC
José María Aguilar - Funciones locales en C# 7
José María Aguilar
.NET Core / .NET
- C# 9.0 – Specification: Partial Methods
Jorge Serrano - Algunas particularidades respecto a la inicialización y validación en setters
Jorge Serrano - Modelo de actores con Akka.Net – II
Joaquín García - MediatR 9.0 Released
Jimmy Bogard - .NET 5: Exploring System.Net.Http.Json namespace
Anthony Giretti - Tidy up your HttpClient usage
Josef Ottosson - 6 Best Practices to Keep a .NET Application's Memory Healthy
Michael Shpilt - Creating a dotnet new Project Template
Rick Strahl - Creating a .NET Core Global Tool
John Smith - Generate INotifyPropertyChanged implementation for MVVM pattern
Kazuki Ota - .NET Internals: System.Threading.Channels - UnboundedChannel (Part 1) - Steve Gordon
Steve Gordon - Changing Serilog Minimum level without application restart on .NET Framework and Core
Niels Swimberghe - Introducing C# 9: Covariant returns
Anthony Giretti - C# in Simple Terms - Code Blocks, Basic Statements, and Loops
Matthew Jones - Calculate the Moon Phase With C#
Khalid Abuhakmeh
<NumberList Count="10" />
Desde el punto de vista del componente <NumberList>
, la recepción de este parámetro es trivial, simplemente indicando el atributo [Parameter]
en su propiedad pública Count
:<ul>
@for (int i = 0; i < Count; i++)
{
<li>@i</li>
}
</ul>
@code {
[Parameter]
public int Count { get; set; }
}
Este mecanismo va bien si queremos pasar el parámetro a un componente específico mediante atributos, pero puede haber ocasiones en las que nos interesa pasar parámetros a todos los componentes que se encuentren por debajo en la estructura jerárquica sin tener que ir pasándolos de uno en uno. Esto puede ser especialmente útil si, como en el diagrama, existen varios niveles de componentes en los que deseamos tener acceso a la misma información.¡Bienvenidos a los cascading values and parameters, o valores y parámetros en cascada!
Probablemente os habréis topado algúna vez con el error HTTP 415 "Unsupported Media Type" mientras hacéis pruebas de APIs. Este código se reserva para que el servidor indique al otro extremo que los datos enviados en la petición no se encuentran en un formato soportado (por ejemplo, hemos enviado datos XML cuando sólo se soportan JSON, o algo similar). El servidor puede determinar la falta de soporte examinando los encabezados Content-Type
o Content-Encoding
, así como el propio cuerpo de la petición.
Y ahora, van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Cómo modificar la convención de nombrado de controladores en ASP.NET Core MVC
José María Aguilar - Publicación self-contained y single-file en .NET Core
José María Aguilar
.NET Core / .NET
- C# 9.0 – Specification: Init-only Setters & Pattern Matching Enhancements & Target Typing & Target-Typed Conditional Expressions & Target-Typed Conditional Expressions & Covariant Returns
Jorge Serrano (¡Vaya serie, amigo! :)) - Introducing DotNet.SystemCollections.Analyzers
Kevin Avignon - IConfiguration does not contain a definition for GetValue
Paul Michaels - Don't Let Your .NET Applications Fail: Resiliency with Polly
Dmitrij Kovaliov - EnsureSuccessStatusCode as an assertion
Mark Seemann - A Subtle Gotcha with Azure Deployment Slots and ASP.NET Core
Phil Haack - A simple pattern for using System.CommandLine with dependency injection
Carmel Eve - C# in Simple Terms - Primitive Types, Literals, and Nullables
Matthew Jones - Automatic factory with Microsoft.Extensions.DependencyInjection and Castle DynamicProxy
Thomas Levesque - .NET 5.0 App Trimming and Potential for Future Progress
Patrick Smacchia - ArrayPool vs MemoryPool—minimizing allocations in AIS.NET
Ian Griffiths - Getting rid of array bound checks, ref-returns and .NET 5
Konrad Kokosa - Streamline .NET Dependency Management with NuGet Meta Packages
James Dawson - ILogger and Null Object Pattern
Christian Findlay - .NET Framework Connection Pool Limits and the new Azure SDK for .NET
Pavel Krymets - Programmable text (and JSON) formatting for Serilog
Nicholas Blumhardt - Using Hangfire and MediatR as a Message Dispatcher
Derek Comartin - Serialize Interface Instances With System.Text.Json
Khalid Abuhakmeh - How to use .NET module initializers in a concrete real use case
Daniel Cazzulino - C# in Simple Terms - Casting, Conversion, and Parsing
Matthew Jones - Creating C# Enums from a SQL Database using T4 Text Templates
Matthew Jones
Como sabemos, al acceder por primera vez a una aplicación Blazor WebAssembly, durante unos segundos aparecerá en el navegador el mensaje "Loading...", indicando que se están descargando los recursos necesarios para que funcione la aplicación.
Vimos también en su momento que este mensaje puede ser modificado a nuestro antojo para sustituirlo por algo más apropiado, como un espectacular spinner:
Sin embargo, si el navegador desde el que estamos accediendo es un vetusto Internet Explorer u otro sin soporte para Blazor WebAssembly, el mensaje de carga se mostrará indefinidamente en el navegador. No se mostrarán errores, ni siquiera por la consola, por lo que el usuario se quedará esperando sin saber que, en realidad, la aplicación no cargará jamás.
Lo que vamos a ver en este post es cómo detectar este escenario e informar al usuario de que para acceder a la aplicación debe usar un browser más moderno.
El código de respuesta HTTP 414, "URI Too Long", se reserva para indicar al cliente que la URI indicada en la petición es demasiado extensa. Esto puede darse en varios escenarios, pero quizás uno de os más frecuentes es cuando se produce un bucle infinito de redirecciones a páginas, cuyos parámetros van aumentando en cada iteración (por ejemplo, el clásico /login?returnUrl=/login
).
Aprovecho para recordaros que el próximo miércoles 30 de septiembre a las 18:30 (CEST, hora peninsular española) estaré con los amigos de SevillaDotNet tomándome un café virtual y hablando de desarrollo web, Blazor, el blog y todo lo que surja ;) Podéis usar este enlace para inscribiros gratuitamente y asistir online.
También está disponible la grabación del evento online de CampusMVP del pasado martes 22, donde José Manuel Alarcón y un servidor charlamos sobre Blazor un buen rato: ¿Qué es Blazor? ¿Qué me aporta? Lo que necesitas saber sobre Blazor.
Y ahora, van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Adivina, adivinanza: ¿por qué no compila este código?
José María Aguilar - Cómo documentar y generar código cliente de nuestras APIs utilizando Swagger/OpenAPI
José María Aguilar
.NET Core / .NET
- C# 9.0 – Specification: Records & Top-Level Statements
Jorge Serrano - Hacer un FeedReader fácilmente en .NET Core 3.1
Jorge Serrano - Announcing more ways, we’re making app development easier on Windows
Kevin Gallo - Injecting services into Serilog filters, enrichers, and sinks
Nicholas Blumhardt - Building amazing cross-platform solutions for iOS, Android and Windows
Nick Randolph - Comparing .NET Mocking Libraries
Dan Clarke - PEM Loading in .NET Core and .NET 5
Scott Brady - How to generate code using Roslyn source generators in real world scenarios
Daniel Cazzulino - Responding to Phone Calls using Twilio and C#
Jamie Maguire - Using LINQ Expressions In C#
Munib Butt - Moving work Out-of-Process using Brighter and RabbitMQ
Derek Comartin - Automating .NET Security Updates
Muhammad Rehan Saeed - Deploying a .NET desktop application using MSIX
Gérald Barré - C# 8.0 nullable references and serialization
Ian Griffiths - NET Core Releases and Support
Jamshed Damkewala - C# in Simple Terms - The Type System
Matthew Jones - Zero Installer, Zero MSIX, Zero Packaging with .NET Single File Apps
Nick Randolph
Pero para entender su utilidad, creo que lo mejor es comenzar por un ejemplo de componente simple como el siguiente, que se encarga de mostrar una colección de objetos
Friend
formateados de una manera determinada:@* File: ItemList.razor *@
@{
var count = 1;
foreach (var item in Items)
{
<div class="counter">Item #@(count++)</div>
<div class="item">
@ChildContent(item)
</div>
}
}
@code
{
[Parameter]
public IEnumerable<Friend> Items { get; set; }
[Parameter]
public RenderFragment<Friend> ChildContent { get; set; }
}
Fijaos que estamos utilizando un RenderFragment
tipado. Si no sabes muy bien lo que es esto, puedes echarle un vistazo al post Componentes con cuerpo en Blazor.
Como hemos podido comprobar, lo único que hace el componente <ItemList>
es recorrer la colección de amigos disponible en la propiedad Items
y, por cada elemento, mostrar un contador que va incrementándose en cada iteración, renderizando el RenderFragment<Friend>
con el ítem actual.<ItemList>
podría ser utilizado desde cualquier otro componente, por ejemplo, de la siguiente manera:<h1>My friends</h1>
<ItemList Items="@Friends">
<p>@context.Name is @context.Age years old</p>
</ItemList>
@code {
public Friend[] Friends { get; set; }
protected override void OnInitialized()
{
Friends = new[] {
new Friend() {Name = "John", Age = 32},
new Friend() {Name = "Peter", Age = 23},
new Friend() {Name = "Ally", Age = 31}
};
}
}
Si ejecutamos un código como el anterior, podremos que ver todo es correcto: la lista de amigos se muestra correctamente. Bueno, todo es correcto, excepto cuando nos preguntamos si este mismo componente podría servir para otros tipos de objeto distintos a Friend
.Esto lo hemos vivido ya antes, muchos años atrás, cuando aún no existían los tipos genéricos en C# y .NET. Porque lo que realmente nos interesaría para lograr una mayor reutilización de código es que el componente
<ItemList>
fuera genérico y pudiera aplicarse a cualquier tipo de datos.El código de estado HTTP 413, "Payload too large", es retornado por los servidores cuando el tamaño de los datos que está recibiendo es demasiado grande y, por tanto, deben ser rechazados. El servidor puede cerrar en esos momentos la conexión para evitar que el cliente continúe enviando datos y, sólo si el problema es transitorio, enviar un encabezado Retry-After
para indicar en cuánto tiempo puede volver a intentarse la operación.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Describiendo APIs ASP.NET Core con Swagger
José María Aguilar - Flushing asíncrono en ASP.NET Core MVC
José María Aguilar
.NET Core / .NET
- Announcing .NET 5.0 RC 1
Richard Lander - C#9 - Top Level Programs
Eduard Tomás - The future of .NET Standard
Immo Landwerth - Understanding Dependency Injection in .NET Core with Quartz.NET example
Bohdan Stupak - Things you need to know as a C# developer - Collections
Sam Fields - .NET Async Programming in a Nutshell
Nelson Parente - C# 9.0: Target-typed expression
Miguel Bernard - .NET Performance Optimisations Don't Have to be Complex - Steve Gordon
Steve Gordon - How to Convert Existing WinForms/WPF Projects to .NET Core
Desislava Yordanova - 6 Easy Ways to Split a PDF Document Using C#
Praveen Kumar - Using OpenAPI with .NET Core
Tom Deseyn - Cross platform diagnostic tools for .NET Core & dotnet-trace for .NET Core tracing in PerfView, SpeedScope, Chromium Event Trace Profiling, Flame graphs and more!
Scott Hanselman
¡Os traigo buenas noticias! Me complace anunciaros que por fin está disponible en el catálogo de CampusMVP el curso en el que he estado trabajando intensamente durante varios meses, y que me consta que muchos estabais esperando: Desarrollo de aplicaciones Web con Blazor.
Su creación ha sido bastante laboriosa porque queríamos ofreceros el mejor y más completo curso sobre Blazor que podéis encontrar en este momento, y no es fácil conseguirlo cuando se trata de una tecnología tan reciente, de la que aún no existe tanta documentación, bibliografía y ejemplos como las hay de otras tecnologías con más años de recorrido. Ha sido duro, pero tanto un servidor como el equipo de producción de CampusMVP que ha participado en su creación, estamos orgullosos del resultado y firmemente convencidos de que lo que hemos logrado: un recorrido práctico, minucioso y profundo del que es, sin duda es el framework que cambiará vuestra forma de desarrollar aplicaciones para la web.
En este post vamos a intentar resolver las siguientes cuestiones:
- ¿Qué es Blazor?
- ¿Me interesa aprender a desarrollar con Blazor?
- Hace poco aprendí ASP.NET Core, ¿significa esto que ya no me valen estos conocimientos?
- ¿En qué consiste el curso de desarrollo con Blazor?
- ¿Cuáles son los contenidos del curso?
- ¿Qué conocimientos previos necesito para seguir el curso?
- Me convence, ¿cuándo empezamos?
Estimadas, estimados, ¡ya estamos de vuelta!
Tras dos meses de parón blogosférico, durante los cuales he andado bastante atareado con otros menesteres, volvemos a la carga. Y no había mejor forma de hacerlo que publicando la entrega número 412 de la serie de enlaces interesantes, que seguro echabais de menos cada lunes ;)
Y por cierto, ya que ha salido el tema, el código de error HTTP 412 (Precondition failed) se produce cuando el acceso a un recurso es denegado debido a que no se cumplió algunas de las precondiciones especificadas a través de encabezados como If-Match
, If-Modified-Since
, If-None-Match
o similares. El objetivo es evitar la ejecución de la acción (GET, POST, etc.) sobre un recurso que se encuentra en un estado incorrecto.
Por si te lo perdiste...
- ¿Qué es Blazor, eso de lo que todo el mundo habla?
José María Aguilar - ¿Quién libera las dependencias cuando finaliza el proceso de una petición en ASP.NET Core?
José María Aguilar
.NET Core / .NET
- Calling Windows APIs in .NET5
Windows Developer - .NET 5 - What you need to know about the latest .NET
Damir Arh - It's 2020 and it is time for text mode with Gui.cs
Scott Hanselman - Producer/consumer pipelines with System.Threading.Channels
Maarten Balliauw - Customizing Trimming in .NET 5
Sam Spencer - Assembly Versioning and DLL Hell in C# .NET: Problems and Solutions
Michael Shpilt - Create a Text File in C#
Mahesh Chand - How to use Async with thread-unsafe objects?
Ahmed Fouad - C# 9.0: Target-typed New Expressions – Make Your Initialization Code Less Verbose
Thomas Claudius Huber - C# 9.0: Improved pattern matching
Miguel Bernard - "await Task.WhenAll" Shows One Exception
Jeremy Clark
La palabra vacaciones, derivada del latín vacans, participio del verbo vacare (estar libre, desocupado), está definida por la RAE como "Período del año en el que los trabajadores descansan temporalmente del trabajo". Y creo que ha llegado la hora de aplicarla, aunque no sea en toda su extensión :)
Como es habitual por estas fechas, os informo que la semana que viene iniciaré mi descanso veraniego, y el blog quedará en modo de bajo consumo hasta septiembre. Durante este tiempo seguiré trabajando en otras cosas (tengo grandes proyectos en curso, ya os iré contando ;)) pero al menos podré hacer jornadas más cortas y descansar un poco los fines de semana, que falta hace.
¡Nos vemos a la vuelta!
Publicado en Variable not found.
Como recordaréis del post anterior, la invocación de métodos estáticos era bastante sencilla, porque básicamente desde Javascript sólo teníamos que conocer el nombre del ensamblado donde se encontraba el código y el nombre del método a ejecutar. El hecho de que el método fuera estático es una ventaja, pues no hay "piezas móviles" en el puzzle.
Sin embargo, si desde Javascript queremos invocar un método de instancia, la cosa se complica un poco porque tendremos que ayudar a Blazor a determinar de qué instancia se trata, y esto a priori no suena sencillo porque Javascript y Blazor viven en dos mundos diferentes (de hecho, en el caso de Blazor Server incluso están físicamente separados). Sin embargo, veremos que las herramientas que ofrece el framework son suficientes para llevarlo a cabo sin liarnos demasiado.
Esta última entrega la dedicaremos precisamente a esto: aprender cómo podemos llamar desde Javascript a métodos de instancia escritos en C#.
Publicado por José M. Aguilar a las 8:05 a. m.
Etiquetas: blazor, blazorinterop, blazorserver, blazorwasm
El código de estado HTTP 411, length required, es enviado al cliente para indicar que la petición no puede ser aceptada si no incluye el encabezado content-length
indicando el tamaño en bytes del cuerpo de la misma.
Ahí van los enlaces recopilados durante la semana pasada, la última entrega antes de comenzar las vacaciones. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Acceder a IIS Express desde otro equipo de la red local
José María Aguilar - Incluir recursos estáticos en una Biblioteca de Clases Razor (RCL)
José María Aguilar
.NET Core / .NET
- Span<T> y P/Invoke
Eduard Tomás - .NET Core / .NET 5: Cómo publicar aplicaciones en un único ejecutable
José Manuel Alarcón - C#9 Records: Mis impresiones
Eduard Tomás - Announcing the Porting Assistant for .NET
Steve Roberts - How to list and download the contents of a GitHub repo in C#
Mark Heath - True and False functions as “oneliners”
Jiří Činčura - C# 9 Deep Dive: Init-only features
Dave Brock - Misusing C#: Multiple Main() Methods
Jeremy Clark - A Few Different Ways to Concatenate Strings in C#
Marinko Spasojevic - NuGet Package Alternatives when Migrating to .NET Core
Derek Comartin - The Magical Methods in C#
Cezary Piątek - Optional Dependencies with Autofac
Adam Storr - Don’t chase the warning! Applying Nullable Reference Types in Fixie
Patrick Lioi - The Easiest Way to Version NuGet Packages
Muhammad Rehan Saeed - C# Futures: Null Check Operator
Jonathan Allen
Cuando fui nombrado MVP por primera vez, jamás pensé que este privilegio fuera a durar tanto. Un par de añitos quizás, lo suficiente como para poder visitar Redmond alguna vez y poder contar a los nietos que "yo estuve allí" ;) Pero diez años más tarde, aquí estamos todavía, con las mismas ganas y entusiasmo de poder seguir formando parte de este club de amigos a los que sigo y admiro tanto. ¡Impresionante!
Esta vez la notificación me ha pillado en una videollamada con el gran Jorge Turrado, amigo y compañero MVP, que me ha sacado del fragor de la batalla diaria para inyectarme la dosis de adrenalina que supone darse cuenta de pronto de que hoy era el día de nombramientos y todavía no me había llegado el famoso email :D Por cierto, Jorge ¡felicidades, por tu merecida renovación!
Muchas gracias a todos los que hacéis posible que me lleve estos momentazos. A los amigos y amigas de blog, porque sin su apoyo no habría sido posible llegar hasta tan lejos; al equipo del programa MVP, por su incansable labor y exquisito trato con todos, y, por supuesto, a mis tres niñas, por consentírmelo todo :)
Finalmente, no me gustaría cerrar este post sin enviar mi más sincera enhorabuena a los nuevos MVP; disfrutad de ese momento tan bonito. Si renováis en el futuro os llevaréis grandes alegrías, pero la primera vez nunca se olvida. Y también enviar un fuerte abrazo (con distancia social, eso sí ;)) a los que repetís galardón: como ya he dicho alguna vez, lo difícil no es sólo llegar, sino también mantenerse.
Publicado en Variable not found.
Va un post rapidito, pero que seguro que puede ahorrar quebraderos de cabeza a más de uno que se encuentre con este problema al iniciar desde Visual Studio una aplicación ASP.NET, ASP.NET Core MVC/Web API, Razor Pages, o incluso Blazor que utilicen por debajo IIS Express.
El problema ocurre justo al ejecutar la aplicación con F5 o Ctrl+F5 desde el entorno de desarrollo; en ese momento, la ejecución se detiene y aparece un cuadro de diálogo con el mensaje:
"Unable to connect to web server 'IIS Express'"
Creo que llevo años encontrándome de vez en cuando con este problema al arrancar las aplicaciones, y nunca entendí muy bien por qué pasaba. Buscaba por la red y solo encontraba soluciones relativas a eliminar el archivo de configuración applicationhost.config
que Visual Studio guarda en la carpeta ".vs" de la solución, a reiniciar el IDE o incluso la máquina, abrirlo como Administrador, o cambiar el puerto en la configuración del proyecto, normalmente algunas unidades por arriba o por abajo que el puerto asignado inicialmente.
Esta última opción es la que más veces me ha funcionado, pero no siempre iba bien, por lo que al final tampoco la identifiqué como una clara receta para paliar el problema que nos ocupa.
Hace unos días me ha vuelto a ocurrir con un proyecto que uso muy a menudo, y, de un día para otro, ha dejado de funcionar y ha comenzado a lanzarme a la cara el maldito cuadro de diálogo. La diferencia es que por fin he podido encontrar una respuesta satisfactoria, al menos para alguno de los escenarios que pueden causar el error :)
Como ya adelantamos en la entrega 404 de enlaces interesantes, los códigos de estado 404 y 410 son muy similares, pues ambos permiten al servidor expresar que el recurso solicitado no existe.
La diferencia entre ambos es que HTTP 410 (Gone) que el recurso existió pero ya no está disponible, mientras que HTTP 404 no permite distinguir entre un recurso que jamás ha existido y uno que simplemente ha desaparecido.
Y ahora vamos con una nueva recopilación de enlaces que, como siempre, espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Streaming en gRPC, parte II: Streaming bidireccional
José María Aguilar - Personalizar la negociación de contenidos en ASP.NET Core MVC
José María Aguilar
.NET Core / .NET
- Announcing .NET 5.0 Preview 6
Richard Lander - Introducing dotnet-monitor, an experimental tool
Sourabh Shirhatti - Introducing C# 9: Improved target typing & Top-level programs] & Improved pattern matching
Anthony Giretti - Empty try with finally
Jiří Činčura - Task.WhenAll / Select is a footgun
Johnny Reilly - Reduce mental energy with C# 9
Dave Brock - Introducing Secret Store
Tom Kerkhove - Differences between String and string in C#
Marinko Spasojevic - It’s all in the Host Class – Part 2: Configuration
Christian Nagel - Multi-Targeted NuGet Package Gotchas!
Derek Comartin - Contribute To The Top 10 Impactful .NET OSS Projects 2020
Khalid Abuhakmeh - Developing Cloud Applications in .NET
Damir Arh - Parse Markdown Front Matter With C#
Khalid Abuhakmeh