Challenges and learnings when migrating a Xamarin.Forms app to .NET MAUI

Author: Simon Hirschel
Software Engineer at BAYOOMED

Co-author: Sebastian Wittor
Project Manager Medical Engineering at BAYOOMED

 

With the release of .NET MAUI 6 in May 2022, we were faced with the question of whether a migration of the no longer supported Xamarin.Forms was necessary for our current project. There was also a deadline for iOS releases. From this point on, it would no longer be permitted to bring apps with outdated frameworks to the App Store. We now had to decide whether to rush blindly into the migration or look for alternative solutions. In the end, we decided to migrate our project to .NET MAUI 6 and later also to upgrade to .NET MAUI 8. You can read how we came to this decision in this blog article.

The first upgrade

Microsoft provides a tool to update smaller Xamarin apps to MAUI. It replaces common usages and some settings with the new MAUI equivalents. Unfortunately, it doesn’t do much more than that and it still took a lot of work to get the app to compile without a lot of bugs. With MAUI, it is also recommended to switch from multiple projects for each platform to a single project with dedicated folders for each platform. We also needed to find replacements for some SOUPs that were essential to the inner workings of our app. These included Xamarin Essentials, which fortunately had a replacement in the MAUI Community Toolkit, and MvvmCross. As there was no equivalent replacement for MvvmCross, we had to remove and replace it. Since we were using MvvmCross for both views, view models, navigation and lifecycle events for the app, this was the biggest hurdle we had to overcome to get the app back up and running. Ultimately, this caused a lot of delays and required rewriting most of our parent views and view models to incorporate newly created events that were similar to the way MvvmCross handled them. In addition, we had to rework our entire navigation system to allow parameters to be passed and returned in the same way as before. Both of these changes were very time consuming and required a lot of testing and debugging before they worked in a way that allowed us to start making changes to the actual functionality of the app and its views.

Changed view

One of the main issues was that controls in .NET MAUI do not work in the same way as in Xamarin.Forms. This difference means that some familiar UI elements require customization to work correctly in the new framework. In addition, the default values for padding, margins and other layout-related variables have changed. As a result, a significant amount of customization is required to make the views look similar to their previous versions. This requires customizing these properties for almost every single view in the application, which can be a time-consuming and painstaking task. Visual issues are also common during the migration process. Many views have inconsistencies that can only be resolved by further rewriting. Each view must be carefully reviewed and modified to fix these visual issues and ensure a consistent and polished look and feel across the application.

MvvmCross

MvvmCross played a crucial role in our development process with Xamarin and saved us a lot of work. It was deeply integrated into our codebase and handled essential aspects such as app launch, app lifecycle and acted as a singleton provider. This extensive integration meant that MvvmCross was interwoven with almost every part of our application. However, the removal of MvvmCross during the migration to .NET MAUI caused numerous issues. We had to rewrite many lifecycle events for our view models as the previous implementation relied heavily on MvvmCross. We also had to develop our own navigation service manually as the built-in navigation provided by MvvmCross was no longer available. Almost all of our views had to be changed due to the absence of MvvmCross. This major overhaul was necessary to ensure that the views worked correctly and complied with the requirements of the new framework. Despite the challenges, overcoming these issues was essential for a successful migration to .NET MAUI and allowed us to maintain and improve the functionality of our application.

Bugs, bugs, bugs

When .NET MAUI was released as “production-ready” with .NET 6, we expected a smooth transition. However, the reality was very different. We encountered numerous errors that had a significant impact on our development process.

Firstly, some view elements did not work as expected. In addition, there were noticeable performance issues that made certain features, such as the carousel view, practically unusable. We also experienced several issues with MAUI running in Visual Studio 2022, especially after certain updates. Connection issues with MAUI on the Mac and deployment issues for iOS in the AppCenter further complicated the situation. Debugging also proved to be particularly difficult. The Visual Studio 2022 debugger often had issues with MAUI, making it difficult to identify and fix problems efficiently. Although fixes were promised, they were often delayed and only made available with the next .NET upgrade. These upgrades sometimes fixed existing issues but also introduced new ones, creating a cycle of troubleshooting and customization. Despite these challenges, we continued to work on the bugs and performance issues and endeavored to make the most of the new capabilities of .NET MAUI. Even though the journey was full of obstacles, each fix and workaround brought us closer to a stable and fully functional application.

Non-app-related challenges

In addition to the technical hurdles, we faced several non-app-related challenges that complicated our migration to .NET MAUI. One of the main issues was the low developer capacity. With only a limited number of developers available, the workload became overwhelming and slowed down progress significantly. In addition, our focus was split due to other ongoing projects, so we could not fully concentrate on the migration process. This was exacerbated by the continuous release of updates and new features for Xamarin, which required additional time and effort to integrate and manage alongside the migration to .NET MAUI. These factors complicated the migration process overall, so we had to carefully allocate our time and priorities to make steady progress despite the constraints.

MAUI migration analysis before the migration attempt

Before embarking on the migration to .NET MAUI, it is important to thoroughly analyze the potential challenges and requirements. Ask yourself the following questions to better estimate the migration effort:

  • SOUP compatibility: Which SOUPs (Software of Unknown Pedigree) need to be replaced because they are not compatible with MAUI?

    Effects: Assess the impact of the individual SOUPs on your project.
    Replacements: Determine if there are MAUI-specific replacements for these SOUPs.

  • Project structure: Does the project use MAUI or native views?

    Experience: Migration with native views tends to be faster, as has been observed in other projects.

    View breakage: Be prepared for views to break due to errors and changes to the default values for control variables.

    • Carousel views: Performance issues are common; consider using a different SOUP instead.
    • GestureRecognizers: There are problems in earlier versions of .NET MAUI.
    • Margins: Many margins need to be adjusted due to changes to the default values.
    • Issue tracking: Monitor issue tracking regularly for updates and corrections.
  • MvvmCross dependency: Do you use MvvmCross?

    Replace: There is no simple alternative, so individual solutions are required:

    • Lifecycle Events
    • Navigation
    • CustomAppStart

    Increase in effort: The migration effort will increase considerably due to the deep integration of MvvmCross in most projects, which leads to a “ripple effect”.

  • Custom views and controls: Do you use custom views, renderers or controls?
    Modifications: Most elements require minor or major modifications to function in MAUI.

    Renderer: Expect complete changes in the way renderers work, including renaming and possible reformulation.

  • Define target .NET MAUI version: Which .NET MAUI version should be migrated to?
    Version selection: Select the last production-ready version.

    Bug Fixes: Be aware that some problems can only be fixed in later versions, which may require further upgrades during development.

  • Please also note:

    • SOUP updates: All SOUPs must be updated and fully validated.
    • Unit tests: Updating unit tests can be time-consuming, especially with significant logic changes and MvvmCross replacements.
    • Documentation: Updating the general documentation to take migration into account.
    • UI realignment: Make sure the user interface matches the Xamarin version, if necessary.
    • Singleton treatment: Adaptation of singleton treatment to MAUI practices.
    • Pipeline customizations: Change build and deployment pipelines as required.
    • External tools: Update and test all other external tools used in the project.

By carefully considering these factors, you can better prepare for the complexities of migrating to .NET MAUI and ensure a smoother transition.

How to migrate – Our recommendations

Migrating to .NET MAUI is a complex process that requires careful planning and execution. Below you will find some recommendations for your migration efforts:

Analyze and plan

  • Review the key questions: Start by analyzing the key questions you formulated in your migration analysis.
  • Test run: Perform a test run of the upgrade wizard to identify additional tasks that need to be completed.
  • Error tracking: Check issue trackers for items you use to anticipate potential problems.
  • Prioritize SOUP replacement: Focus on replacing important SOUPs like MvvmCross early in the process.
  • Common coding: Consider common coding for the most critical parts of the application to avoid problems later on.
  • Incremental changes: Divide the migration into smaller, manageable tasks so that you are not overwhelmed.

Distribute resources

  • Dedicated focus: Ensure that developers can fully concentrate on the migration without significant distractions.
  • Freeze the project: Freeze other parts of the project until the migration is complete to maintain focus.
  • Team stability: Avoid major changes in the team during the migration in order to maintain continuity and dynamism.
  • Minimize cascading changes
  • Careful implementation: Try to implement changes in a way that minimizes the need for further adjustments in other parts of the application.

By following these recommendations, you can better manage the migration process and mitigate potential issues, leading to a more successful transition to .NET MAUI.

Sounds exciting and would you like to talk about it?