Case Study

Minnesota Secretary of State

Umbraco 7 to Umbraco 14. .NET Framework to .NET Core.

Minnesota Secretary of State website

The situation

The Office of the Minnesota Secretary of State runs the public website for elections and voting as well as business filings and liens. It's the front door for a large part of how residents and businesses interact with the state.

It ran on Umbraco 7 with a .NET Framework backend. Both were out of date and needed to be upgraded to the current - and most importantly supported - versions.

Leaving an old platform alone feels like the low-risk option because nothing is visibly broken. But over time the platform and code the site was built on become out of date. Letting a system become out of date opens up security holes that won't be patched. And there is the issue of technical stack. The older the stack gets, the harder it is to find people who will work on it.

Why it was hard

Umbraco 7 to a current version is not a straight upgrade. There is no in-place path that gets you there. It is a rebuild of the application with a content migration attached and the reasons are worth being specific about.

The backend had to be rewritten, not ported. Umbraco moved onto ASP.NET Core, which means the old application is running on a framework that does not support the new version. Anything that reached into the request pipeline the old way has to be rethought rather than translated.

The backoffice was rewritten out from under every extension. Umbraco 14 replaced the AngularJS backoffice with a new one built on web components. Custom property editors, dashboards and backoffice sections written for the old backoffice do not carry over. They get rebuilt against a different API with a different mental model.

The content editing primitives changed. The legacy grid and macros were how a v7 site composed flexible pages. Current Umbraco does that with block-based editors. Every piece of content built on the old primitives needs a new home and the mapping is rarely one to one. This is usually the largest single piece of the work.

Packages disappear. A site that has been running for years accumulates third-party packages. Some have a modern equivalent. Some were abandoned years ago and the functionality has to be rebuilt or dropped.

What was at stake

This is a state government website, which changes the calculation in a few ways.

Availability is public. An outage on a commercial site is a bad afternoon. An outage on the Secretary of State site during a filing deadline or an election period is a story and it erodes trust in the office rather than in the vendor.

Accessibility is an obligation, not a preference. State sites are held to published accessibility standards and a migration is the moment when conformance either gets addressed properly or gets carried forward as debt for another decade.

URLs are public infrastructure. People link to this site from legal filings, agency documentation and other government sites. Breaking a URL does not just cost search ranking. It breaks references that are sitting in documents nobody is going to update.

How I sequenced it

The old site stayed up and unchanged for the entire build. Nothing about the migration was allowed to depend on modifying the thing that was still serving the public.

  1. Inventory first. Every document type, template, property editor, package and piece of custom code, sorted into migrate, rebuild or drop. The drop column matters. A migration is a good opportunity to remove features that are no longer used.
  2. Build the new application clean. Current Umbraco on .NET Core, with the document types and templates rebuilt rather than converted. Carrying the old shapes forward adds significant time.
  3. Rebuild the editors. Property editors and backoffice extensions against the new API and the legacy grid content remapped onto block-based editors.
  4. Migrate content, then verify it. There are tools that have been open sourced to help with the data migrations. Each section of content needs to be verified that the migration was successful.
  5. Map every URL. A full redirect map from the old structure to the new one, tested before launch.
  6. Cut over with a way back. A staging cutover and a rollback plan in case there is an error during the cut over.

What changed after

The site is on a supported version. Security patches apply. Moving to the next version is routine maintenance rather than another rebuild, because the hard break between Umbraco 7 and the current generation is behind them.

The backend is on .NET Core, which means modern hosting, modern tooling and a hiring pool that is growing rather than shrinking.

Stack

C#.NET CoreUmbraco 14SQL ServerAzureCI/CD

Visit the live site →

Stranded on Umbraco 7 or 8?

If you are on an unsupported version with a .NET Framework backend, I can describe the shape of the work in one conversation.

Get a migration assessment →

More on Umbraco version migrations.