My experience with migrating my app from Xamarin.Forms to .NET MAUI

I’ve been eager to rewrite some of my personal apps from Xamarin.Forms to .NET MAUI, but since all of them are dependant on map functionality, I had to wait until the arrival of .NET 7, since the .NET 6 release of MAUI didn’t ship with map support. Since .NET 7 shipped in November 2022, I was able to start rewriting my apps. I started with the most simple one, which is a single-page application (not that kind) that shows the different parking zones in my local municipality. The parking zones are drawn on a map as polygons. When you click on a zone, it gets highlighted and some info about the zone is shown in an info overlay. I posted on Twitter about my progress, but I wanted to do a full post about my experience with trying to migrate to .NET MAUI.

NOTE: Your milage may vary – my experience with the migration may differ greatly from yours. This is just to highlight the pain points that I had during my attempt. Having a machine with preview releases probably did not help me here.

The TL;DR:

Positives:

  • Easy to copy over pages and convert namespaces
  • Eliminated the need for a couple of plugins

Negatives:

  • Workloads are a hassle
  • Trying to migrate while .NET 7 was in preview was a mistake
  • Lots of “smoke and mirrors”/yak-shaving
  • Project file would randomly break
  • App would crash in Release mode on iOS without reporting error to App Center

I’ll go into more detail on the different points as I go through my process.

Initial migration

My initial attempt was to have a go at migrating while .NET MAUI was still on .NET 6, so even though maps weren’t ready yet, I could still migrate the “outlining” project and just comment out the code that didn’t work. I converted the XAML namespaces, the using statements and the packages that were either redundant or had an update for them. Turns out a lot of it didn’t work since I didn’t have a working map (shocker), so the project laid dorment for a while.

.NET 7

When .NET 7 hit preview, I updated Visual Studio 2022 Preview and tried to upgrade the project. I cleaned the bin/obj folder, but I got some random build errors for Android. After restarting VS, they were gone for a while, but after doing some changes and building a couple of times they would come back so restarts of VS were frequent.

After this, I pulled in the NuGet package for MAUI maps and was able to comment back my code. After some code changes, the polygons were properly drawn on the map, at least for Android (as shown in the previous Twitter link). I hadn’t looked at when you click on the zones yet, as I had issue on iOS when drawing the polygons.

Polygons + iOS = 💔

In the app, I set the fill color of the different parking zones to be transparent, so that you can actually see the different street names. On iOS, the transparency only seemed to take effect on one of the several drawn polygons. I tried isolating what might be the error here, but it was so time consuming that I ended up leaving the project for a while and betting on that it would get fixed in a patch release of the MAUI maps package.

Oops, my project broke

After not having done much work on the project for a while, I picked it back up to see if I could isolate the problem with iOS further. But this time my project wouldn’t build. I tried clean/rebuild, delete bin/obj, restart VS, restart VS again. Nothing. I also tried updating my maui workloads via the CLI. For a while here, I was only able to build clean .NET 7 MAUI projects and not .NET 6 MAUI projects. After having given up completely, I created a clean new .NET 7 MAUI project and copied everything over to it and was able to build. But, I was still stuck with the polygon iOS problem. Sigh.

Smoke and mirrors

I was also thrown for a loop a couple of times during my process, which wasn’t related to MAUI at all. The API I used to fetch data about the different parking zones for altered the structure of the data without notice. I spent more time than I want to admit figuring this one out. Like I said, I was testing this out while the .NET 7 version of MAUI was in preview so a lot of stuff would randomly work or not work. Another one was a setting I applied to Visual Studio, which led to some hours of yak-shaving. At this point, I was pretty fed up with this whole process.

Update ALL the packages

After having put down the migration for a second time, I picked it up again later to see if my issue was magically resolved. After updating the MAUI maps NuGet package, it was working on iOS! After double checking that it was working on both platforms, I was ready to start publishing.

As I usually do, I start publishing on Android because I know this process is way faster and less error-prone than what it is for iOS. If I have an app that needs to be rolled out on both platforms simultaneously, I might start with iOS to make sure everything works. This time I wanted to save the “best” for last.

Certificates… Why’d it have to be certificates?

Anyone who’s worked with publishing apps for iOS has had to deal with the nightmare process that is certificates and provisioning profiles. Even after having worked with this process for eight years, I still never get it right on the first try. This time was no different. When trying to build the app for iOS in release, I got an error along the lines of that the self-signed certificate was not trusted. Turns out that XCode doesn’t ship with the latest intermediate signing certificate that you need, so you have to download that from the Apple Developer site. Also, there are three different types of them with varying expiration date, just to make you wonder which is the correct one you should choose. Delightful.

After spending an evening fixing this issue, I was finally able to create an ipa file I could upload to App Store Connect.

Submit for review

After submitting my update for review in App Store Connect, I got it back with them claiming the app crashed instantly on startup. Weird, since I remember testing the app on a physical device. I checked App Center and there was one crash report along the lines of: Attempting to JIT compile method […] while running in aot-only mode. Googling the error gave me some indication that this could happen when running a MAUI iOS app in Release mode.

I tried to distribute the app through App Center so that I would be able to reproduce the bug, but when trying to start the app on my iPad, I got the error that the app’s integrity could not be verified. Great. This usually indicates that something is wrong with the certificate and/or the provisioning profile, and I thought I had just gotten it right. After a lot of back and forth, it looks like I had to use an Ad-Hoc provisioning profile to sign the app to explicitly include my iPad for testing. More time spent.

After finally getting the app to work on my iPad, I reproduced the bug and the app instantly crashed on start. Never been so glad to see my app crash. I went to App Center in hopes of seeing my recent crash being reported, but nothing. I went to Twitter to ask for help on how to move along here, but honestly, I am so tired of trying to get this to work that I might put this whole thing on pause again.

Conclusion

I’m happy that I am just trying to do this with one of my personal apps and not for a client project. I will say, most of the time spent here has been caused by smoke and mirrors plus Apple’s provisioning nightmare, but a lot of time has been spent on tooling as well. I thought about rewriting another app I have that is a bit more complex, but I’m glad I waited off on it. I might give it a shot now, but this experience did leave a bad taste in my mouth when I had so much trouble with such a simple app. I hope you have a far better experience than I did, but I just wanted to share how my journey was.

7 thoughts on “My experience with migrating my app from Xamarin.Forms to .NET MAUI”

  1. Hi Andreas, thanks for sharing your experiences. Did you use the .NET upgrade tool or did you attempt a manual migration? I’m still putting off migrating my apps but I really should try it soon.

    1. Hi Dave! I did a manual migration, seeing as my app was so small. I might try the upgrade tool on my next app and see how that works.

  2. I tried XF years ago. All the same problems, especially with Apple. Their process is such nonsense.
    I finally tried out Flutter, which was fun, but managing the backend in C# and the front end in Dart proved to be too much for a one person show. In the end, there was plenty of weirdness in Flutter, too.
    Working on Blazor now, hoping that Maui will eventually stabilize.
    Thanks for the article.

  3. It’s been a long road too for us, though while some are definitely self-inflicted pangs (taking the opportunity to actually structure the code better, add tests, etc) we’re definitely feeling the pain too.

    For us, it’s:
    – Hot reload that isn’t 100%
    – ScrollView doesn’t always work
    – Splash works until it doesn’t, and it might be completely different depending on the platform
    – Random android failures
    – Needing ios layout changes everywhere

  4. Hey,

    i migrated now 2 customer projects.
    One was a XF to Maui, one was a Xamarin.iOS Xamarin.Android to .net.iOS and .net.Android.

    My experience was: Keep your fingers away from the upgrade tool.
    For me the best practice was to create a completely new blank Maui solution.
    Than i installed all the needed Nuget packages or switched to an alternative one. I also experienced that i don’t need one or two Nugets anymore, so i refactored it out and use a .net7 feature instead.
    Than i set up all my core stuff with the new dependency injection. Yes this is a bit of work, but its worth.
    After that i start to copied every screen/view model one by one and also changed the bindings to the new once.
    Now i have 2 projects, fully migrated to .net maui/native with any workaround inside.
    For me, the change to the new dependency injection and binding was essential. I don’t want a half Xamarin and half Maui solution.

    But the most annoying thing in the whole process was Visual Studio for Mac …. This IDE was and is a nightmare. 1000 of restarts, 10 000 times to delete bin/obj, buttons was freezing, debug windows always disappear after every time you click on debug. This was the greatest time eater in the whole process.
    I hope so much that Rider is supporting Maui fully as soon as possible.

    1. Hi Stefan! Thanks for sharing your experience. We did almost the same for another project of mine where we (almost) did everything manually. I also tried some of it on VS for Mac and had about the same experience as you. Glad you were able to land the migrations, though! -Andreas

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.