Organize your .NET MAUI MauiProgram / Startup file

Table of Contents

If you’re an ASP Net Core guy, you should be familiar with the nightmare that is startup file organization. Every ASP Core application startup file can include configurations, middleware declaration, dependency injection definition, authentication configs, policies amongst other things.

So long story short: heavy applications have large messy unreadable startup files with hundreds of lines of, hard to scroll through, code.

In this post, we are going to write about what we consider to be the best practices for startup/program organization files while developing the .NET Multi-platform App UI (.NET MAUI) project. How we can make it better and how to make it more maintainable.

While we are working on a project, our main goal is to make it work as it is supposed to and fulfill all the customer’s requirements. But wouldn’t you agree that creating a project that works is not enough? Shouldn’t that project be maintainable and readable as well?

It turns out that we need to put a lot more attention to our projects to write them in a more readable and maintainable way. The main reason behind this statement is that probably we are not the only ones who will work on that project. Other people will most probably work on it once we are done with it.

Application Startup

.NET MAUI enables apps to be initialized from a single location. The MauiProgram class is the entry point to the application, setting up configuration and wiring up services the application will use.

The MauiProgram class

In .NET MAUI, the MauiProgram class provides the entry point for an application. Because .NET MAUI apps are bootstrapped using the .NET Generic Host it enables apps to be initialized from a single location and provides the ability to configure fonts, services, and third-party libraries.

TIP

For more details, you can see some older posts where I talk about the structure of the MauiProgram and its builder.

Important

My server was deleted. My provider gives me no reason about it. All posts are lost but I find a method of how I can get them manually but it will take time. Until that, you can not see my older posts.

Services Available in Startup

.NET MAUI provides certain application services and objects during your application’s startup. The services available to each method in the MauiProgram class are described below. The framework services and objects include:

  • Configuration

  • Host
    Used to build the application request pipeline.
  • ILoggingBuilder
    Provides a mechanism for creating loggers.
  • IServiceCollection
    The current set of services configured in the container.

Looking at each method for the MauiAppBuilder class in the order in which they are called, the following methods can be used:

  • ConfigureAnimations
  • ConfigureDispatching
  • ConfigureEffects
  • ConfigureFonts
  • ConfigureImageSources
  • ConfigureMauiHandlers

Best practice for organizing your MauiProgram class file

So, as you might have guessed, here is where extension methods come to the rescue. Learning to organize your MauiProgram.cs is part of being a good C# programmer and having extension methods in your arsenal is a must. By the end of this article, you will learn a neat and simple trick to improve the organization of your startup files and spare yourself the pain of endless startup file scrolling in your future projects.

Extension methods can be used to extend an existing type without creating a derived type, recompiling, or modifying the original one.

In our case, we are going to create an extension method for

  • Fonts
  • Handlers
  • Services

Extension methods

As a brief example, let’s add our configuration wrapper in another file using the extension methods.

namespace OrganizeStartup
{
    public static class ConfigExtensions
    {
        public static MauiAppBuilder RegisterFonts(this MauiAppBuilder builder)
        {
            return builder.ConfigureFonts(fonts =>
            {
                // Your fonts here...
                //fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
            });
        }

        public static MauiAppBuilder RegisterHandlers(this MauiAppBuilder builder)
        {
            RegisterMappers();

            return builder.ConfigureMauiHandlers(handlers =>
            {
                // Your handlers here...
                //handlers.AddHandler(typeof(MyEntry), typeof(MyEntryHandler));
            });
        }

        public static MauiAppBuilder RegisterServices(this MauiAppBuilder builder)
        {
            // Add your services here...

            // Default method
            //builder.Services.Add();

            // Scoped objects are the same within a request, but different across different requests.
            //builder.Services.AddScoped();     

            // Singleton objects are created as a single instance throughout the application. It creates the instance for the first time and reuses the same object in the all calls.
            //builder.Services.AddSingleton();  

            // Transient objects lifetime services are created each time they are requested. This lifetime works best for lightweight, stateless services.
            //builder.Services.AddTransient();  


            return builder;
        }
    }
}

Now, to use it, we just need to import the namespace OrganizeStartup.Extensions in our project, and voilà! Thanks to the magic of IntelliSense, our new methods are now used for any object of type MauiAppBuilder.

public static class MauiProgram
{
	public static MauiApp CreateMauiApp()
	{
		var builder = MauiApp.CreateBuilder();
		builder
			.UseMauiApp<App>()
			.RegisterFonts()
			.RegisterHandlers()
			.RegisterServices();

		return builder.Build();
	}
}

Check out this Microsoft docs page for more examples about extension methods.

Files organization

Depending on the project you can structure how you can manage your code and files. In our case, for large projects in order to reuse code, and better reading we are going to split each configuration by file. That way we are getting the best project organization and separation of concerns (SoC). See below.

Tip

You can use a partial class for all the configuration extension methods.

Conclusion

In this article,  our main goal was to familiarize you with the best practices when developing a .NET MAUI project. Some of those could be used in other frameworks as well, therefore, having them in mind is always helpful.

Resources

You can find a full example code solution here.

If you find that something is missing, don’t hesitate to add it in a comment section.

Thank you for reading the article and I hope you found something useful in it.

Share this content!

Facebook
Twitter
LinkedIn
Telegram
WhatsApp