Comparando MauiAppBuilder con el WebApplicationBuilder

Contenido

Con el nuevo MauiAppBuilder llega una nueva forma de crear aplicaciones en .NET, utilizando MauiApp.CreateBuilder(). En esta publicación comparo este enfoque con los enfoques anteriores, discuto por qué se realizó el cambio y miro el impacto. En el próximo post voy a ver el código detrás MauiApp y MauiAppBuilder ver cómo funcionan.

Este articulo pertenece a la serie: Explorando MAUI App Builder. En esta serie habláremos sobre algunas nuevas características incluidas en .NET MAUI.

Creado aplicaciones .NET hoy en día

Para poder hacer una comparacion justa debemos traer a la mesa a los predecesores, o al menos la fuente, de donde sale la idea de crear el MauiAppBuilder en .NET 6 con .NET MAUI.

Antes de ver .NET 6, creo que vale la pena ver el proceso de las aplicaciones ASP.NET Core 3 ya que este diseño esta construido sobre el host genérico hoy en dia. Teniendo esto en cuenta, podemos mostrar 3 paradigmas:

  1. Host.CreateDefaultBuilder(): Construido encima del Host genérico de ASP.NET Core.
  2. WebApplication.CreateBuilder(): El nuevo host para aplicaciones web en .NET 6.
  3. MauiApp.CreateBuilder(): El nuevo host para aplicaciones multiplataformas con .NET MAUI en .NET 6.

Para tener una mejor idea de las diferencias, he reproducido el típico código de «startup» en las siguientes secciones, lo que debería hacer que los cambios mostrados sean más evidentes.

ASP.NET Core 3.x/5: the generic HostBuilder

ASP.NET Core 3.x trajo algunos grandes cambios en el código de inicio para ASP.NET Core. Anteriormente, ASP.NET Core solo se podía usar realmente para cargas de trabajo web/HTTP, pero en .NET Core 3.x se hizo un movimiento para admitir otros enfoques: «servicios de trabajo» de larga duración (para consumir colas de mensajes, por ejemplo), servicios gRPC, servicios de Windows y más. El objetivo era compartir el marco base que se creó específicamente para crear aplicaciones web (configuración, registro, DI) con estos otros tipos de aplicaciones.

El resultado fue la creación de un «Host genérico» (a diferencia de la Alojamiento Web), y un «re-platforming» de la pila ASP.NET Core encima. En lugar de un IWebHostBuilder, había un IHostBuilder.

Series: Exploring ASP.NET Core 3.0 (andrewlock.net)

Con estos cambios y el arduo trabajo del equipo de ASP.NET se trajo a la mesa cambios como Endpoint Routes (Enrutamiento). El enrutamiento fue uno de los cambios que en versiones anteriores estaba limitada y que hoy en día es una de las cosas mas llamativas dentro de ASP.NET Core.

Con todos los cambios que se hicieron en ASP.NET Core 3 con Razor Pages, podemos tener una clase Startup similar a esta:

...
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseStaticFiles();

        app.UseRouting();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
        });
    }
}
...

Dentro de ASP.NET Core 5 hubieron pocos cambios importantes con lo cual la configuración es similar.

En .NET 6 hay soporte para la configuracion del host en su version anterior pero hay algunos cambios en la clase Startup

ASP.NET Core 6: WebApplicationBuilder

Con todas actualizacion de C# 10, BCL y ASP.NET Core ahora en .NET 6 tenemos un nuevo estilo donde podemos tener todo en un solo lugar.

...
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}

app.UseStaticFiles();

app.MapGet("/", () => "Hello World!");
app.MapRazorPages();

app.Run();
..

Aqui se pueden apreciar los cambios, a continuación los mas notables:

En el ejemplo anterior hay mucho menos código, pero ¿es necesario?

El porque de todo

Una de las cosas en la que .NET 6 se ha enfocado es en los «principiantes». Como principiante en ASP.NET Core, hay muchos conceptos que se deben entender antes de ir mas profundo.

Las actualizaciones en .NET 6 se enfocan en eliminar la «inicialización» asociada con el inicio y ocultar conceptos que pueden ser confusos para los principiantes.

Por ejemplo:

  • Declaraciones using no son necesarias al comenzar.
  • De manera similar a los namespace, es un concepto innecesario cuando comienzas.
  • Program.Main() Trae mas preguntas que respuestas.
  • La configuración no se divide entre dos archivos,  Program.cs e Startup.cs.
  • Etc…

Además, tenemos los nuevos tipos WebApplication y WebApplicationBuilder. Estos tipos no eran estrictamente necesarios para lograr los objetivos anteriores, pero hacen que la experiencia de configuración sea algo «más limpia».

.NET Maui: MauiAppBuilder

Con la evolución de Xamarin a .NET MAUI (Multi-platform App UI) podemos notar una actualización que cambia la forma de como nosotros inicializamos nuestros aplicativos completamente.

.NET MAUI implementa el patron .NET Host Builder haciendo que el inicio de nuestros aplicativos estén alineados a ASP.NET y Blazor. Esto ayuda a que los desarrolladores .NET puedan reutilizar conceptos ya aprendidos, lo cual hace que la curva de aprendizaje sea menor.

Ejemplo MauiProgram.cs (que entiendo que deberia llamarse Startup.cs)

...
public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
            });

        return builder.Build();
    }
}
...

Si comparamos la implementación de .NET MAUI con la implementación de ASP.NET Core 6 podemos ver que se no goza de las grandes actualizaciones como las Declaraciones de nivel superior.

Cuando veo que en los proyectos nativos se usa MauiProgram.CreateMauiApp() me pregunto: ¿por qué se llama así? ¿No deberia llamarse Startup? ¿Al final esa es su función, no?

protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();

En los ejemplos oficiales de .NET MAUI se puede apreciar como el archivo y la clasa se llaman Startup. Esperemos que estos sean los cambios futuros, recordemos que estamos en Preview todavia.

Puedes verlo aqui.

Pero mas importante que eso, ¿Por qué necesitamos dos archivos de configuración? ¿Por qué lo necesito junto App.xaml? ¿Por qué tengo que tener dos archivos para configurar mi aplicativo?

Ejemplo App.xaml.cs

...
	public partial class App : Microsoft.Maui.Controls.Application
	{
		public App()
		{
			InitializeComponent();
      MainPage = new MainPage();
		}

		protected override Window CreateWindow(IActivationState activationState)
		{
			Microsoft.Maui.Controls.Compatibility.Forms.Init(activationState);

			this.On<Microsoft.Maui.Controls.PlatformConfiguration.Windows>()
				.SetImageDirectory("Assets");

			return new Microsoft.Maui.Controls.Window(new MainPage());
		}
	}
...

En el ejemplo podemos ver como estamos definiendo tanto el MainPage como la compatibilidad para windows. Estos metodos pueden ser facilmente utilizados desde Startup.cs (dando por hecho que se llamará asi) creando las extensiones necesarias para esto.

¿Deberiamos estar preocupados?

Pues no, no deberiamos. Podemos crear nuestras aplicaciónes siguiendo el patrón definido por el equipo de .NET MAUI sin ningún problema.

Sin embargo, creo que tienes que estar de acuerdo que parece estamos comentiendo los errores que la versión de .NET 6 WebApplication ya ha solucionado.

Esto me pone a pensar en lo siguiente:

  • A medida que los proyectos vayan creciendo tendremos un montón de lambdas anidadas.
  • Al igual que ASP.NET 3 estaba utilizando Startup.cs y Program.cs en .NET MAUI estamos utilizando Startup.cs y App.xaml.cs.
  • No estamos aprovechando lo mas llamativo del enfoque de .NET 6 y C# 10 en los templates.

En términos generales Startup.cs es un script de arranque de procedimiento (en su mayoría) que resuelve muchos problemas pero que le falta un poco para que este a la par con su hermano dentro de .NET 6.

Hay que comentar que unos de los beneficios de .NET 6 era simplicar los inicios de los nuevos desarrolladores y ASP.NET Core 6 WebApplicationBuilder simplifica muchas cosas para estos.

Debemos recordar que .NET MAUI todavia esta en preview, esperemos los nuevas noticias relacionados a este apartado.

La mayor parte de la configuración ocurre en MauiAppBuilder

Comencemos viendo el MauiAppBuilder.

var builder = MauiApp.CreateBuilder();

MauiAppBuilder es responsable de 4 cosas principales:

  • Agregar configuración mediante builder.Configuration.
  • Agregar servicios mediante builder.Services.
  • Configurar logs mediante builder.Logging.
  • Generar configuración builder.HostBuilder.

Vamos a verlos uno por uno…

ConfigurationManager

MauiAppBuilder expone el tipo ConfigurationManager para agregar nuevos orígenes de configuración, así como para acceder a los valores de configuración, como lo mostre en mi post anterior.

ServiceCollection

ambién expone IServiceCollection directo para agregar servicios al contenedor DI. Entonces, mientras que con el host genérico se podia hacer algo como esto:

...
var builder = MauiApp.CreateBuilder();
builder.ConfigureServices(services => 
{
     services.AddSingleton<MainPage>();
     services.AddSingleton<MainPageViewModel>();
});
...

Con MauiAppBuilder puedes hacer lo siguiente:

var builder = MauiApp.CreateBuilder();
builder.Services.AddSingleton<MainPage>();
builder.Services.AddSingleton<MainPageViewModel>();

Loggin

el mismo modo, para los logs, en lugar de hacer:

...
var builder = MauiApp.CreateBuilder();
builder.ConfigureLogging(logging=> 
{
     logging.AddFile(); // this is just an example
});
...

Puedes hacer algo similar a esto:

var builder = MauiApp.CreateBuilder();
builder.Logging.AddFile(); // this is just an example

Esto tiene exactamente el mismo comportamiento, solo que en una API más fácil de usar. Para aquellos puntos de extensión que dependen de IHostBuilder directamente se expone la propiedad Host.

Por ejemplo, cuando las librerias empiecen a utilizar este patron y sus beneficios podremos utilizar el MauiAppBuilder con UseLibrary() para llamar la propiedad Host, por ejemplo.

builder.Host.UseLibrary();

Entonces, MauiAppBuilder es donde tu deberias hacer todas tus configuraciones a excepcion de esas que se hacen en App.xaml.cs.

MauiApp

Una vez que haya configurado todo lo que necesitas en MauiAppBuilder tu puedes llamar Build() para crear una instancia de MauiApp.

...
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder.UseMauiApp<App>();

        return builder.Build();
    }
...

Para las personas nuevas en MAUI se van a encontrar con el metodo UseMauiApp() que llama la clase App que es la crea nuestro aplicativo.

Resumen

En esta publicación describí cómo el arranque de las aplicaciones moviles, ahora con .NET MAUI, ha cambiado en .NET 6.

Muestro los nuevos tipos MauiApp y MauiAppBuilder introducidos en .NET 6, discuto por qué se introdujeron, algunas de las ventajas que aportan y comentamos algunas sugerencias.

Finalmente, discuto los diferentes roles que desempeñan las dos clases y cómo sus API hacen que la experiencia de inicio sea más simple. En la proxima entrega vamos a ver algunas cosas interesantes.

Si todavia no me sigues en las redes, lo puedes hacer en Twitter o Linkedin. Sera genial verte por allá.

¿Qué opinas de este contenido?
 
Luis Matos

Luis Matos

I help professionals and companies to create value solutions. I am a Systems Engineer, blockchain executive, and international mobile application speaker. Founder of the Malla Consulting Agency and several international technology communities.
Suscribirte
Notificar de
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x

Buscar en el sitio