Last September, we had an extraordinary opportunity to share our findings and experience migrating our first Optimizely solution to .NET Core. This event occured at the Optimizely Dev Meetup in Montreal. I was presenting alongside my colleagues Pierre Vignon and Eric. So, as the title suggests, our goal was to give tips & tricks on the migration of an Optimizely solution to .NET Core. This effort obviously came with some challenges!
Here is a vague overview of the steps the process involves:
You will need to plan the time required to do the migration:
Lessons & learned: The most overlooked part of this section were the dependencies of our solution. We learned at the project runtime stabilization step that some modules/plugins/dependencies weren't compatible anymore under .NET, so we had to find alternatives. Some of which weren't available except by re-implementing them from scratch. This is by far one of the biggest bottlenecks of a migration. We had to put our own efforts to migration certain plugins, e.g., a color picker.
Optimizely also switched of image processing plugin from .NET Fx to .NET. It's now referring ImageSharp. You will have to consider changing all transformation logics inside your solution to something else, preferably using ImageSharp.Web.
You will have to convert all projects to the new csproj
format. This process can be simplified using the .NET Upgrade Assistant. Refer to the Optimizely documentation for more information. They also have created an extension over the upgrade assistant which is going to help you during the migration.
The goal of this step is to convert all projects of the solution as quickly as possible to the newest format. Keep in mind this operation can only be done by a single developer or by pair programming if necessary. You can't have two developers on such major changes, you will simply end up with Git conflicts while trying to merge. So, typically, a single developer per project is recommended on this phase. Centralize your efforts on the migration, but not on making sure the site is compiling, it's expected not to compile after the first time the upgrade assistance as been ran.
As soon as all csproj
are converted, you can easily share the rest of the conversion with all developers. From that point, you will have a lot of compilation errors. Here's a simple representation of items you need to check per project:
Developers has the habit to comment some part of the code when testing any changes, they've made. It's sure is a usual development style some people use, but do not take this reflex to comment everything just to reach your goal to compile the project. This is totally counter intuitive and you might even end forgetting critical parts to be migrated later.
As for database migrations, we followed Microsoft's recommendations and removed all past migrations. The only thing that left was the database context and the database models. Technically speaking, they are already deployed to production, so they are no longer necessary anyway. Adding more migration will simply create a difference with the existing schema and your modification.
Once all projects are compiling, you will then probably face a lot of runtime exceptions, especially at the first boot. Here are the commonly found issues we faced during our migration:
@helper
usagedotnet ef
. You'll find all necessary resources to debug what's causing the hitches.After the first successful boot, you will surely face other complications that will require your team's attention. Notably:
Keep a good attention of your browser developer console, you'll probably find a couple of errors here and there, mainly responsible because the default JSON serializer is now using camel case instead of pascal case under .NET Fx.
It's very important at this phase that all developers work conjointly to find as much bugs as possible. Stack them as much as you can into the backlog. It's expected there will be a lot, so at least you can track their progress and present them to your QA team once you will reach the quality assurance phase.
In parallel, another person can work on adjusting your DevOps automations. Typically, the biggest part that will require many efforts will be the application compilation itself. Since we're switching from .NET Fx to .NET, it's best to switch using the .NET CLI under your scripts. Another thing to keep in mind; If you're deploying in DXP, make sure every package name are unique, otherwise you will receive an error stipulating the package has already been uploaded. In .NET, Optimizely prevents duplicates. The advantage though is that you can reuse an existing package to re-make a deployment without the need to re-upload it first.
In summary:
*.config
configuration and the newest appsettings.json
one. The old configuration isn't working anymore. If you prefer, you could simply delete these old files in your repository to prevent any confusions.
appsettings.Integration.json
linux-x64
architectureTo this point, you've gathered an enormous quantity of bugs inside your backlog. You now want the full team to fix them all together. Obviously, you will want all majorly impacting bugs to be fixed first, especially the ones causing crashes, until you reach certain nebulous bugs where you can't even tell if they've been provoked by the migration or if it was already there to begin with.
Couple of things to keep in mind:
You're near the end. Your team of developers has found and fix every possible bug, now it's turn for your QA team to double check the stability of the whole site. They should get back to the reported bugs inside the backlog and verify every one of them to make sure they're fixed. In any case, they can reopen them if any issue arises. Also, very important they make a full regression testing, independently of the number of bugs logged or not, they want to verify every part of the site, even the most unused sections.
Your QA team will then decide together whether the stability of the site is worthy for production or not. In all scenarios, they will probably log more bugs inside the backlog for the developers to look for them afterwards. If they decide the site is ready to be released, a code freeze should be put in place to prevent any further change that could cause unwanted regressions. If in contrary they find the site too unstable for their taste, they should put the developers precisely on priority items that are blocking the release to production. Other nonessential and non critical bugs that can be fixed after, should be postponed.
In the meantime, another of your team member should have already started communications with Optimizely's team to prepare for the Go-Live. A release plan should detail every expected step your team needs to take for it. You also want to coordinate your DNS switch to your newest .NET application instance.
You've tested over and over, and your QA team is satisfied with the stability of your site, you are now ready for Go-Live. Even thought you've made your best to test everything, you should still expect things can go wrong during the procedure. Fortunately, if in any ways something goes bad, you can still use the old production environment, which should still be intact.
A general idea of the steps to take:
All in all, I loved the experience, it was quite a challenge! The things all developers loved the most during this adventure was the speed the site took to load. It's so fast, it's extremely unrecognizable from the .NET Fx variant of the site. Optimizely also published some metrics on the subject and I'd say they aren't far fetched at all.