.NET MAUI Project Structure and Multi Targeting Step by step Implementation and Top 10 Questions and Answers
 Last Update: April 01, 2025      10 mins read      Difficulty-Level: beginner

Understanding .NET MAUI Project Structure and Multi-Targeting: A Beginner’s Guide

Introduction

.NET Multi-platform App UI (MAUI) is an innovative tool by Microsoft aimed at enabling developers to create cross-platform applications using .NET. By leveraging a single codebase, MAUI allows developers to target multiple platforms, including Windows, iOS, Android, and macOS, efficiently. This guide will delve into the structure of a .NET MAUI project and how it handles multi-targeting, providing a detailed overview that will help beginners grasp these concepts easily.

Setting Up .NET MAUI

Before exploring the project structure and multi-targeting, ensure that you have the necessary tools installed:

  • Visual Studio 2022: The latest version of Visual Studio supports .NET MAUI.
  • .NET 6 SDK: MAUI is built on .NET 6, so the SDK is essential.
  • Platform-specific SDKs: Depending on the platforms you plan to target, ensure you have the necessary SDKs installed. For Windows, this is typically pre-installed. For iOS, you need Xcode (on a Mac), and for Android, the Android SDK through Android Studio.

Creating a New .NET MAUI Project

Once your development environment is set up, create a new .NET MAUI project:

  1. Launch Visual Studio and select "Create a New Project".
  2. From the "Create a New Project" dialog, search for ".NET MAUI App" and choose it.
  3. Click "Next" to provide a project name, location, and solution name.
  4. Select the preferred target platforms. Initially, you can leave the defaults, as you can modify them later.
  5. Click "Create" to generate the project template.

.NET MAUI Project Structure Overview

A typical .NET MAUI project includes the following directories and files:

  1. Platforms/:

    • This directory contains platform-specific folders:
      • Android/: Contains configurations, resources, and assets specific to the Android platform.
      • iOS/: Contains configurations, resources, and assets specific to the iOS platform.
      • Windows/: Contains configurations, resources, and assets specific to the Windows platform.
      • macOS/: Contains configurations, resources, and assets specific to the macOS platform.
  2. MauiProgram.cs:

    • Acts as the entry point for the application in .NET 6.
    • Configures the MauiApp and its dependencies via the MauiApp.CreateBuilder() method.
    • Registers services, configures HTTP clients, and sets up routing.
    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();
        }
    }
    
  3. Resources/:

    • Stores shared assets like images, fonts, and XAML styles.
    • Use the MauiImageSource.FromResource method to reference these assets.
  4. App.xaml/App.xaml.cs:

    • Defines the shared application resources.
    • Handles the lifecycle of the application, such as startup and termination.
    <Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="YourNamespace.App">
        <Application.Resources>
            <!-- Application resource dictionary goes here -->
        </Application.Resources>
    </Application>
    
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
            MainPage = new MainPage();
        }
    }
    
  5. MainPage.xaml/MainPage.xaml.cs:

    • The default page in your application.
    • Contains the XAML markup for the UI and the code-behind logic.
    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="YourNamespace.MainPage">
        <StackLayout>
            <Label Text="Welcome to .NET MAUI!"
                   HorizontalTextAlignment="Center"
                   VerticalOptions="CenterAndExpand" />
        </StackLayout>
    </ContentPage>
    
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }
    }
    
  6. obj/ and bin/:

    • Automatically generated directories containing build outputs, debug information, and intermediate files.

Multi-Targeting in .NET MAUI

Multi-targeting refers to the capability of a application to run on multiple platforms using a single codebase. Here’s how .NET MAUI achieves this:

  1. Shared Codebase:

    • Most of your application logic, UI, and services reside in shared projects or code files.
    • This ensures that you write code once and it can be reused across different platforms.
  2. Platform-Specific Code:

    • Sometimes, you need platform-specific functionality, which can be encapsulated in platform-specific projects or files.
    • Use #if directives to conditionally compile code based on the target platform.
    #if ANDROID
    // Android-specific code here
    #elif IOS
    // iOS-specific code here
    #elif WINDOWS
    // Windows-specific code here
    #elif MACCATALYST
    // macOS-specific code here
    #else
    // Default code for all other platforms or common code
    #endif
    
  3. Platform Configurations:

    • The platform-specific folders in the Platforms/ directory contain configuration files and assets tailored to each platform.
    • For example, Android/AndroidManifest.xml for Android, iOS/Entitlements.plist for iOS, and Windows/Package.appxmanifest for Windows.
  4. MauiProgram.cs:

    • Configuration settings in MauiProgram.cs can be customized based on the target platform.
    • Use #if directives to apply platform-specific settings when creating the MauiApp builder.
    public static class MauiProgram
    {
        public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiApp<App>()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                });
    
            #if ANDROID
            builder.ConfigureMauiHandlers(handlers =>
            {
                handlers.AddHandler<CustomView, CustomViewHandler>();
            });
            #endif
    
            return builder.Build();
        }
    }
    
  5. Build Process:

    • During the build process, .NET MAUI compiles the shared code and merges it with the appropriate platform-specific code and resources.
    • Visual Studio automatically handles this process, ensuring that the final application is optimized for each target platform.

Best Practices for Multi-Targeting

  1. Minimize Platform Specific Code:

    • Keep platform-specific code to a minimum to maintain a single point of truth.
    • Use #if directives only when necessary.
  2. Use Dependency Injection:

    • Leverage dependency injection to inject platform-specific services and components.
    • Register platform-specific implementations in MauiProgram.cs.
  3. Leverage .NET MAUI Controls:

    • Utilize the built-in .NET MAUI controls, which are platform-agnostic and provide a native look and feel for each target platform.
    • Custom controls can be created using partial classes to handle platform-specific rendering.
  4. Organize Code into Services and Repositories:

    • Separate business logic, data access, and other core functionalities into services and repositories.
    • Share these components across platforms, ensuring consistency and reusability.
  5. Use Platform-Specific APIs Wisely:

    • When you need to use platform-specific APIs, encapsulate them in interfaces and provide platform-specific implementations.
    • This separation allows you to inject the correct implementation based on the target platform.

Example of Encapsulating Platform-Specific Code

Suppose you need to use platform-specific APIs to access the camera. You can create an interface and provide platform-specific implementations as follows:

  1. Define an Interface:

    public interface ICameraService
    {
        void CapturePhoto();
    }
    
  2. Implement the Interface for Each Platform:

    • Android:

      #if ANDROID
      using Android.Hardware.Camera2;
      using Android.Hardware.Camera2.Params;
      
      public class CameraService : ICameraService
      {
          public void CapturePhoto()
          {
              // Implement Android-specific camera capture logic here
          }
      }
      #endif
      
    • iOS:

      #if IOS
      using AVFoundation;
      
      public class CameraService : ICameraService
      {
          public void CapturePhoto()
          {
              // Implement iOS-specific camera capture logic here
          }
      }
      #endif
      
    • Windows:

      #if WINDOWS
      using Windows.Media.Capture;
      using Windows.Media.MediaProperties;
      
      public class CameraService : ICameraService
      {
          public void CapturePhoto()
          {
              // Implement Windows-specific camera capture logic here
          }
      }
      #endif
      
  3. Register the Service in MauiProgram.cs:

    public static class MauiProgram
    {
        public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiApp<App>()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                })
                .ConfigureServices(services =>
                {
                    #if ANDROID
                    services.AddSingleton<ICameraService, CameraService>();
                    #elif IOS
                    services.AddSingleton<ICameraService, CameraService>();
                    #elif WINDOWS
                    services.AddSingleton<ICameraService, CameraService>();
                    #endif
                });
    
            return builder.Build();
        }
    }
    
  4. Inject and Use the Service:

    public partial class MainPage : ContentPage
    {
        private readonly ICameraService _cameraService;
    
        public MainPage(ICameraService cameraService)
        {
            InitializeComponent();
            _cameraService = cameraService;
        }
    
        private void CapturePhotoButton_Clicked(object sender, EventArgs e)
        {
            _cameraService.CapturePhoto();
        }
    }
    

Conclusion

.NET MAUI simplifies the process of creating cross-platform applications by providing a unified project structure and multi-targeting capabilities. By understanding the organization of a .NET MAUI project and how multi-targeting works, you can efficiently develop applications that run seamlessly across various platforms. Adhering to best practices, such as minimizing platform-specific code, using dependency injection, and leveraging built-in controls, will further enhance your development experience and the quality of your applications. With .NET MAUI, you can take advantage of the power of .NET while targeting multiple platforms with a single codebase.