.NET MAUI Xamarin

.NET MAUI – SDK-style Project File

.NET MAUI SDK-style project file structure and its details.

In the earlier posts, we have seen how to create a new MAUI project from the template and then went on to build and debug the application in VS Code and automated the process to an extent with Comet for. NET Mobile.

Now in this post, we’re going to see the inner details of a .NET MAUI SDK-style project file as it is designed to target multiple platforms from a Single project.

This is different from Xamarin.Forms, as Forms creates an individual head project for each of the platforms it targets and a .NET Standard project for writing platform-independent Forms code (which gets added as a reference to those head projects).

In Xamarin.Forms, only the shared .NET Standard library is of SDK-style project whereas the head project of the platforms still follows the conventional Franken-style project.

Below is the .NET MAUI SDK-style project:

.NET MAUI SDK-style Project File
.NET MAUI SDK-style Project File

It’s an XML file. In the root Project node, the Sdk attribute defines the SDK that it targets.

Since .NET 6 is another step forward towards one unified .NET (.NET Framework + .NET Core + Mono). Mono includes Xamarin.iOS and Xamarin.Android now rechristened as net6.0-ios and net6.0-android respectively.

Indeed, the concept of one .NET started in .NET 5 itself by merging .NET Framework and .NET Core. Now Mono joins the party, thus resulting in a single BCL (base class library) – Microsoft.NET.Sdk across all platforms where .NET is available.

All the project-level properties are enclosed within the PropertyGroup node. Whereas ItemGroup node where the dependencies like Project(s) referenced, NuGet package(s) added, Resource definitions and all others.

On line #3, since .NET MAUI is multi-targeting by design, the TargetFrameworks list (and is separated by semicolon) is mentioned. Here all the TFM are prefixed with net6.0-. This is because of the single BCL. And then the actual platform is specified (iOS, Android, MacCatalyst. Windows will soon join in to this single project, mostly in the upcoming preview, as net6.0-windows). (TFM – Target Framework Moniker – a symbolic notation)

Optionally, RuntimeIdentifier (RID) can also be configured to identify target platforms where the application runs (simulator / physical device), architecture it targets (x86, x64, arm64), and sometimes a specific version of OS like windows10, ios13, android30. For example, maccatalyst-arm64 (for Apple Silicon M1) / win-x64 (for Windows 64-bit OS)

On line #4, the OutputType of this MAUI project will be an executable (an App) on each of the platforms.

From .NET 6 Preview 6 onwards, .NET MAUI is now a Workload quite like Mobile Development with .NET (for Xamarin Development). Since MAUI is an optional workload, it won’t get installed with Visual Studio for now. Maybe in a future version. For time being, this has to be manually installed with the below .NET CLI command in an elevated prompt.

dotnet workload install maui

This now includes Essentials as part of the Maui framework, no separate package as in the case of Xamarin, and it brings Non-UI services, such as accessing sensors like accelerometer, compass, gyroscope, orientation …, all under one roof.

On line #5, with the concept of Workload, instead of referencing the NuGet packages, this is now simplified as a project-level option as <UseMaui>true</UseMaui>. Developers working on WinForms/WPF backgrounds are familiar with this kind of option introduced in .NET Core 3.

On line #6, SingleProject, this is one of the main design goals of .NET MAUI, multi-targeting from a single project.

On line #7, RootNamespace, the root namespace for the types contained within this project.

On line #8, ApplicationTitle, which will be the name that appears as Title in the list of installed Apps.

On line #9, ApplicationId, the unique identifier for the App (using UTI scheme).

On line #10, ApplicationVersion, the version # for the App (X.Y.Z, follows a three-part convention w.r.t Apps).

On line #11, AndroidVersionCode, an integer, we need to increment this value for the App package to upgrade an existing installation.

On line #15, MauiImage, this is a newly introduced node, which helps in including SVG images and is based on the popular Resizetizer component, this will internally resize the images based on the platform needs. Relieving much of the developer’s headache in including a set of images on multiple platforms. Setting the IsAppIcon attribute to true will make it an app icon. Read more about the .NET MAUI App Resources in this article.

On line #24, if the project is added as a reference, a ProjectReference node enclosed within the ItemGroup node with an Include attribute set to the relative path of the referenced project file will be added as shown.

On line #27, PackageReference, this is a recurring node and it repeats for every NuGet package that is added to this project.

This simplifies many of the properties of the Franken-style project (have provided the screenshot of the Android project below).

Since this is still in the preview phase, things will change as it takes shape (as Windows target will soon get onboard into this single project file). Will provide an update, if there is any noticeable change introduced.

And in the next post will look into the application flow from where it starts to how the UI appears in the foreground.

Stay connected as we continue to learn and share the experiences from this exciting journey of being a software developer.


By Vijay Anand E G

A software professional with over a decade long industry experience in developing products that spans across desktop, mobile, and web.