The Future of Multi-Platform .NET Application Development with WinUI, Net6 and the Uno Platform

In my previous post I started a series talking about using the Uno.Extensions that the Uno Platform team have been working on. This post was supposed to be a follow-on post but instead I want to recap one of the topics in the previous post. In case you missed the announcement, version 4.3 of the Uno Platform was recently announced. There’s plenty in the announcement that covers general improvements as well as all the work going into Toolkit, Themes, Extensions and Figma support. A significant point to note is that the Uno Platform now supports .NET 6.0.300 (the same runtime .NET MAUI uses) – this means that if you’re starting a new project today, you can not only target WinUI (instead of UWP), you can also target .NET6 for iOS, Android, macOS and Catalyst, and of course .NET6 for Web (via WebAssembly).

Before continuing this series, looking at the Uno.Extensions, I wanted to revisit how to get started with a new solution. The steps in the previous post are still all corrrect – the only change I would make would be to use the unoapp-winui-net6 template instead of the unoapp-winui template, which will give you a single Mobile project targeting net6, rather than individual iOS, Android and MacOS projects that use Xamarin.

In this post, we’re actually going to use an additional template that’s available via the Uno.Extensions.Templates package. Let’s create our application and then we’ll walk through what’s created by the template and how you can use it to jump start your next Uno Platform application. The first thing to do is to install the templates (nuget):

dotnet new --install Uno.Extensions.Templates::2.1.0-dev.190

In this case I’m going to be installing the latest (as of this post) dev version which references the latest dev release of the Uno.Extensions. If you want to stay on the stable releases of Uno.Extensions, then install the stable release of the templates.

Now that we have the templates installed, we can create our project using the dotnet new command:

dotnet new unoapp-extensions-net6 -o UnoWinUIExtSample

When you open the created solution in Visual Studio, you’ll notice that the solution structure has been updated and extended to include additional projects.

Here’s a quick summary of the changes to the solution structure:

  • Platforms folder – to make it easier to focus on the code of your application, the different targets are grouped in the Platforms folder.
  • Mobile project – the template leverages the new single-project format for iOS, Android and MacOS delivered by the Maui team. This will evolve with subsequent Uno releases to include additional targets such as the WinUI target
  • Tests folder – two additional projects that are configured for unit tests (Tests) and UI Tests (UITests), making it easier to get started with test driven development. Particularly writing UI Tests is a great way to validate the functionality of your application and ensure that with each update there is no regression.
  • UnoWinUIExtSample class library – the class library, with same name as the application, is designed for all the business logic of your application. This can include your models, services and viewmodels.
  • UI project – the Shared project has been renamed to UI to reflect the nature of the code that should be contained in this project. Typically this will include any UI related classes such as Pages, UserControls, Converters, Styles etc

Hosting

My previous post walked through adding Host support to an application in order to leverage capabilities such as dependency injection. The Uno.Extensions templates already have this code included and it has been extracted into a separate partial class called App.xaml.host.cs. Here is a typical example of the BuildAppHost method that’s included:

private static IHost BuildAppHost()
{ 
	return UnoHost
			.CreateDefaultBuilder()
#if DEBUG
			// Switch to Development environment when running in DEBUG
			.UseEnvironment(Environments.Development)
#endif
			// Add platform specific log providers
			.UseLogging(configure: (context, logBuilder) =>
			{
				// Configure log levels for different categories of logging
				logBuilder
						.SetMinimumLevel(
							context.HostingEnvironment.IsDevelopment()?
								LogLevel.Debug:
								LogLevel.Information);
			})

			.UseConfiguration(configure: configBuilder=>
				configBuilder
					.EmbeddedSource<App>()
					.Section<AppConfig>()
			)

			// Enable localization (see appsettings.json for supported languages)
			.UseLocalization()

			// Register Json serializers (ISerializer and ISerializer)
			.UseSerialization()

			// Register services for the application
			.ConfigureServices(services =>
			{
				// TODO: Register your services
				//services.AddSingleton<IMyService, MyService>();
			})


			// Enable navigation, including registering views and viewmodels
			.UseNavigation(RegisterRoutes)

			// Add navigation support for toolkit controls such as TabBar and NavigationView
			.UseToolkitNavigation()

			.Build(enableUnoLogging: true);

}

In this post we’re not going to walk through the details of each line but as you can see the BuildAppHost method configures a number of features such as Environment, Logging, Configuration, Localization, Serialization and Navigation. The idea is that you can use this template to launch into writing just the code necessary for your application.

More to come in the next post but feel free to get started with the Uno.Extensions templates.

Source code for this post