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!
martes, 12 de noviembre de 2019
ASP.NET Core MVCUn alumno del curso de ASP.NET Core 3 en CampusMVP, me preguntaba hace unos días qué había pasado con la llamada al método SetCompatibilityVersion() que veíamos en la plantilla de proyectos ASP.NET Core MVC y Razor Pages desde la versión 2.1:
public void ConfigureServices(IServiceCollection services)
{
   services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
Esta llamada era incluida de serie en los nuevos proyectos ASP.NET Core desde la versión 2.1, pero en la versión 3.0 ya no aparece. Y probablemente también os llame la atención a quienes ya habéis trabajado con ASP.NET Core 2.x, así que he pensado que sería interesante comentarlo por aquí.

¿Para qué sirve la llamada a SetCompatibilityVersion() ?

Como contamos hace algún tiempo, esta novedad de ASP.NET Core 2.1 era un mecanismo de defensa que nos protegía ante cambios de comportamiento inesperados que podían surgir conforme el framework MVC iba evolucionando en sus distintas revisiones menores, es decir, las numeradas como 2.x.

El objetivo era que los pequeños cambios introducidos de una a otra versión no bloquearan a los usuarios a la hora de hacer un upgrade del framework en proyectos existentes y, al mismo tiempo, permitir que el equipo de producto pudiera seguir haciéndolo evolucionar. Es decir, la idea era que si teníamos una aplicación MVC creada con ASP.NET Core 2.0 y queríamos actualizar el marco de trabajo a la versión 2.2, las funcionalidades o cambios introducidos no se aplicaran al proyecto a no ser que lo indicásemos expresamente mediante una llamada a SetCompatibilityVersion().

En la práctica, esto implicaba que en todos los proyectos ASP.NET Core 2.x, el comportamiento del framework era el de la versión 2.0, excepto cuando se indicara lo contrario con SetCompatibilityVersion(). De esta forma:
  • Proyectos inicialmente creados con ASP.NET Core 2.0 continuarían comportándose de la misma manera aunque actualizáramos la versión del framework a la 2.1 o 2.2. Pero si queríamos estar a la última y aprovechar las novedades de estas revisiones, podíamos hacer la llamada expresa a SetCompatibilityVersion() en su clase Startup.
     
  • En proyectos nuevos creados con la versión más reciente del framework, dado que la llamada a SetCompatibilityVersion() ya se incluía por defecto en la plantilla apuntando a la versión en curso, estaríamos aprovechando todas las últimas novedades desde el principio.
Pero la llamada a SetCompatibilityVersion() es sólo la parte visible de la estrategia utilizada para poder introducir cambios en revisiones sin "salpicar" a los usuarios de las versiones actuales o anteriores del marco de trabajo.

Y creo que vale la pena comentarla porque el procedimiento seguido puede ser una buena inspiración cuando programemos APIs, frameworks o componentes que evolucionan con cierta periodicidad y necesitamos mantener un cierto nivel de compatibilidad entre versiones.

¿Cómo se introducen novedades en el framework sin romper nada?

Cuando en la versión 2.2 de ASP.NET Core se iban a introducir en MVC nuevas características que podían afectar a usuarios de la versión 2.0 o 2.1, la forma de trabajar era más o menos la siguiente:
  • Se implementaban las nuevas features de forma que su funcionamiento pudiera ser activado o desactivado, normalmente modificando sendos switches del objeto MvcOptions que solemos utilizar para configurar el framework MVC. Por ejemplo, en ASP.NET Core 2.2 se introdujo la propiedad booleana EnableEndpointRouting para habilitar o deshabilitar la nueva infraestructura de rutado endpoint routing.

  • El valor inicial de los switches era establecido de forma que las novedades de la versión 2.2 no entraran en funcionamiento por defecto. Siguiendo con el ejemplo anterior, la propiedad EnableEndpointRouting valía inicialmente false, lo que conseguía que el endpoint routing no estuviera activo por defecto, asegurando que no se rompía ningún proyecto existente.

  • La llamada a SetCompatibilityVersion() pasándole un valor igual o superior a Version_2_2 modificaba los switches para habilitar las features introducidas en la versión 2.2 y anteriores. Continuando con el ejemplo, esto quiere decir que se establecía la propiedad EnableEndpointRouting a true, habilitándose así el endpoint routing en el proyecto MVC.

  • Si un desarrollador quería utilizar todas las características de la versión más reciente excepto alguna en particular, siempre podía establecer la compatibilidad a la 2.2, pero luego desactivar manualmente los switches en cuestión:
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc()
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
            .AddMvcOptions(options =>
            {
                options.EnableEnpointRouting = false;
            });
    }
    

Entonces, ¿por qué no aparece la llamada a SetCompatibilityVersion() en proyectos ASP.NET Core 3.0?

Pues básicamente, porque de momento no es necesario. Como podemos observar en la siguiente captura de pantalla, la llamada a SetCompatibilityVersion() sigue existiendo en IMvcBuilder, pero observad que la mayoría de sus posibles valores están marcados como obsoletos porque ya no se utilizan:

Intellisense mostrando el método SetCompatibilityVersion()

El uso de opciones como Version_2_1 o Version_2_2 no tienen sentido porque las funcionalidades introducidas opcionalmente en dichas versiones ya forman parte de ASP.NET Core 3.0 MVC, bien como features obligatorias o bien como switches que por defecto vienen habilitados de serie. Hay que tener en cuenta que un salto de versión entre 2.x y 3.0 permite introducir breaking changes.

A día de hoy sólo podríamos utilizar esta llamada con el valor Version_3_0 o Latest, lo cual, en la práctica, no hace absolutamente nada, pues esta versión framework ya establece por defecto el nivel de compatibilidad a la versión 3.0.

Por tanto, en este momento no tiene sentido que la plantilla de proyectos ASP.NET Core MVC y Razor Pages incluya esta llamada. Sin embargo, conforme el producto continúe evolucionando, es posible que aparezcan nuevas funcionalidades y switches, y entonces probablemente veremos de nuevo aparecer la llamada a SetCompatibilityVersion() en el contenido inicial de nuestros proyectos o se nos recomendará utilizarla en los proyectos existentes para hacer uso de estas novedades.

Publicado en Variable not found.

Aún no hay comentarios, ¡sé el primero!