The New .slnx Solution Format: A Simple Migration Guide for .NET 10
Learn the new XML-based .slnx solution format in .NET 10, why it beats the old .sln file, and how to migrate safely with one CLI command.
Think about a class attendance register. The old register was a fat notebook full of secret codes, page numbers, and student ID numbers written in a strange order. Only the head teacher could read it. Every time two teachers wrote in it on the same day, the entries clashed and someone had to fix the mess by hand.
Now imagine a new register: a clean sheet that simply lists each student's name, one per line, in plain words. Anyone can read it. When two teachers add a new name, the two lines almost never clash.
That is exactly the change happening in .NET. The old .sln file is the fat notebook full of secret codes. The new .slnx file is the clean, plain sheet. In .NET 10, the clean sheet becomes the default. This guide shows you what changed, why it is better, and how to move over safely in one command.
What is a solution file, anyway?
When you build a real app, you rarely have just one project. You might have a web API, a class library for your database code, and a test project. A solution is a small file that ties these projects together so your tools know they belong to the same app.
The solution file answers three simple questions:
- Which projects are part of this app?
- How are they grouped into folders?
- Which build settings (like
DebugandRelease) should they use?
For over twenty years, this file was called .sln. It worked, but it was never meant for humans to read or edit by hand.
The old .sln file: why it hurt
Open an old .sln file in Notepad and you will see something scary. Here is a small piece of one.
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApi", "WebApi\WebApi.csproj", "{A1B2C3D4-1111-2222-3333-444455556666}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
EndGlobalLook at those long codes inside the curly braces. Those are GUIDs (globally unique identifiers). They are long random labels the tools use to tell projects apart. A human cannot read them, and a human should never edit them.
The format had three real pains:
- It was hard to read. Lines were long, repeated, and full of GUIDs.
- It caused Git merge conflicts. When two people added a project at the same time, Git often got confused and you had to untangle it by hand.
- It was long. A solution with three projects could take 35 lines or more.
The old .sln pain cycle
Steps
Edit .sln
Two devs add projects
Push to Git
Both touch the same lines
Conflict
Git cannot auto-merge
Fix by hand
Slow and risky
The new .slnx file: clean and simple
The .slnx file does the exact same job, but it is written in XML. XML is a simple way to describe things with tags, a bit like labelled boxes. Here is a full .slnx file for the same three projects.
<Solution>
<Project Path="WebApi/WebApi.csproj" />
<Project Path="DataAccess/DataAccess.csproj" />
<Project Path="Tests/Tests.csproj" />
</Solution>That is the whole file. No GUIDs. No secret codes. Just three lines that say "here are my projects." You can read it, a teammate can read it, and Git can merge it easily.
The table below shows the difference at a glance.
| Point | Old .sln | New .slnx |
|---|---|---|
| File type | Custom text with GUIDs | Plain XML |
| Easy to read | No | Yes |
| Lines for 3 projects | About 35 | About 5 |
| Git merge conflicts | Common | Rare |
| Edit by hand | Risky | Safe and simple |
When did this become the default?
This is the key date for you to remember. Starting with .NET 10, when you run dotnet new sln, the CLI creates a .slnx file by default instead of a .sln file. This is a small breaking change, but a friendly one. Older SDKs still create the old .sln file.
So in .NET 10 you get the new format for free on any brand-new solution. For your existing solutions, you migrate them with one command, which we will cover next.
| Tool | First version with full .slnx support |
|---|---|
| .NET CLI / SDK | 9.0.200 |
| Visual Studio 2022 | 17.13 |
| JetBrains Rider | 2024.3 |
| VS Code (C# Dev Kit) | Supported |
| MSBuild | 17.12 |
How to migrate: one command
Migration is short and safe. Open a terminal in the folder that holds your .sln file and run this.
dotnet sln MySolution.sln migrateThat is it. The command reads your old MySolution.sln and writes a new MySolution.slnx right next to it. The best part: your original .sln file is not deleted. It stays exactly where it was. So if anything looks wrong, you simply keep using the old file and try again later.
Here is the flow in plain steps.
Safe migration path
Steps
Check SDK
Need 9.0.200+
Run migrate
dotnet sln migrate
Open .slnx
Verify projects
Build & test
Make sure it works
Delete .sln
Only when happy
Let me walk through each step like a checklist.
Step 1: Check your SDK version
You need .NET SDK 9.0.200 or newer for the migrate command. Check what you have.
dotnet --versionIf the number is older than 9.0.200, install a newer SDK first. In .NET 10 you are already past this line.
Step 2: Run the migrate command
Move into the folder with your solution and run the migrate command shown above. If your solution file has a different name, use that name. After it finishes, you should see a new file named MySolution.slnx appear.
Step 3: Open the new file and check it
Open MySolution.slnx in your editor. You should see one <Project> line for each project that was in the old solution. If you used solution folders to group projects, you will see <Folder> tags too. Here is what a grouped solution looks like.
<Solution>
<Folder Name="/src/">
<Project Path="src/WebApi/WebApi.csproj" />
<Project Path="src/DataAccess/DataAccess.csproj" />
</Folder>
<Folder Name="/tests/">
<Project Path="tests/Tests/Tests.csproj" />
</Folder>
</Solution>Notice how the folders read like a real folder tree. This is far clearer than the old format, where folders were just more GUIDs hidden in the text.
Step 4: Build and test
Now prove it works. Point your build at the new file and run it.
dotnet build MySolution.slnx
dotnet test MySolution.slnxIf both succeed, your migration is good. Open the solution in Visual Studio or Rider too, just to be sure the IDE is happy.
Step 5: Delete the old .sln (only when you are happy)
Once the new file builds, tests pass, and your IDE opens it cleanly, you can delete the old .sln file. Do this as a separate, calm step. There is no rush.
Updating your build pipeline (CI)
If you have a CI pipeline (the robot that builds and tests your code when you push), check whether it names the solution file directly. Many pipelines have a line like this.
- run: dotnet build MyApp.slnAfter migrating, point it at the new file.
- run: dotnet build MyApp.slnxA small but important tip: do not keep both MyApp.sln and MyApp.slnx in the same folder long-term if you also use bare commands like dotnet build with no file name. When two solution files sit side by side, some tools will not know which one to pick and may stop with an error. During migration this overlap is fine for a short while, but tidy it up once you trust the new file.
What does .slnx not change?
This is good news for nervous beginners. The .slnx file only changes how the solution is written down. It does not change your projects, your code, your NuGet packages, or how your app runs.
- Your
.csprojfiles stay the same. - Your build still produces the same output.
- Your tests run the same way.
- Your code does not change at all.
Think of it like rewriting the attendance register in neat handwriting. The students are the same. Only the page looks better.
A quick before-and-after example
Suppose you start with this old layout.
MyApp.sln
src/WebApi/WebApi.csproj
src/DataAccess/DataAccess.csproj
tests/Tests/Tests.csprojYou run one command.
dotnet sln MyApp.sln migrateNow you have MyApp.slnx sitting next to MyApp.sln, with this clean content.
<Solution>
<Project Path="src/WebApi/WebApi.csproj" />
<Project Path="src/DataAccess/DataAccess.csproj" />
<Project Path="tests/Tests/Tests.csproj" />
</Solution>You build, you test, you delete the old file. Done. The whole thing takes a couple of minutes for most projects.
Common questions and small gotchas
A few practical notes that save you time:
- Older teammates. If a teammate is still on an SDK older than 9.0.200, they cannot open
.slnx. Make sure the whole team upgrades before you delete the old.sln. - Add and remove still work. You can run
dotnet sln MyApp.slnx add SomeProject.csprojandremovejust like before. The commands work on both formats. - Hand editing is now safe. Because the file is simple XML, you can add a
<Project>line by hand if you want. This was a bad idea with the old format. - Source control is happier. Commit the
.slnxfile and your future merges will be far cleaner. This is the biggest day-to-day win.
Why the team will thank you
Let me explain the Git win a little more, because it is the reason most teams switch. Git is the tool that saves every version of your code and lets many people work together. When two people change the same file in the same place, Git asks a human to sort it out. This is called a merge conflict, and it is slow and easy to get wrong.
The old .sln file was a magnet for these conflicts. Adding a project meant touching several lines, all near each other, all full of GUIDs. Two people adding two projects on the same day almost always clashed.
The new .slnx file fixes this by being short and orderly. Adding a project usually means adding just one tidy line. Two people adding two different projects now touch two different lines, so Git merges them on its own. No human has to step in.
Over a year, on a busy team, this saves real hours and real headaches. It is a small file change that pays back every single week.
What if I am not on .NET 10 yet?
You do not have to wait for .NET 10 to enjoy the new format. As long as you have SDK 9.0.200 or later, the dotnet sln migrate command works and the .slnx file builds. The only thing .NET 10 adds is making .slnx the default for brand-new solutions.
So a sensible plan for an older team is:
- Upgrade everyone to SDK 9.0.200 or later.
- Migrate one small repository first as a test.
- Once it feels safe, migrate the bigger repositories.
- Move fully to .NET 10 when you are ready, with the format already in place.
This way the solution-format change and the framework upgrade do not pile onto the same risky afternoon. You take them one calm step at a time.
Quick recap
- A solution file lists the projects in your app and how they are grouped.
- The old
.slnformat was hard to read, full of GUIDs, and caused Git merge conflicts. - The new
.slnxformat is plain XML: short, clear, and easy to merge. - In .NET 10,
dotnet new slncreates a.slnxfile by default. - Migrate with one command:
dotnet sln MySolution.sln migrate. Your old file is kept, so rollback is easy. - You need SDK 9.0.200+; Visual Studio 17.13+, Rider 2024.3+, and VS Code all support it.
- Migration changes only the solution file, not your code, projects, or builds.
- Update your CI pipeline to point at the
.slnxfile, then delete the old.slnonce everything passes.
References and further reading
- Introducing SLNX support in the .NET CLI (.NET Blog)
- Breaking change: dotnet new sln defaults to SLNX (Microsoft Learn)
- New, simpler solution file format (Visual Studio Blog)
- The new .slnx solution format migration guide (Milan Jovanovic)
- Migrate from .sln to .slnx in .NET 10 (codewithmukesh)
Related Posts
EF Core Migrations: A Detailed Beginner Guide for .NET
Learn EF Core migrations step by step. Add, apply, revert, and ship database changes safely with simple examples, diagrams, tables, and best practices for .NET 10.
How to Create Migrations for Multiple Databases in EF Core (.NET 10)
Learn how to create EF Core migrations for multiple databases like SQL Server, SQLite, and PostgreSQL using separate migration projects, with simple examples.
Exploring C# File-Based Apps in .NET 10: Run a Single .cs File
Learn how C# file-based apps in .NET 10 let you run a single .cs file with dotnet run, add packages with directives, and grow into a full project.
How to Create Command-Line Console Applications in .NET
A beginner-friendly guide to building command-line console apps in .NET 10 with the dotnet CLI, arguments, options, and System.CommandLine.
Run C# Scripts With dotnet run app.cs: No Project Files Needed
Learn to run C# scripts with dotnet run app.cs in .NET 10 — no project files, no setup. Add NuGet packages, pass arguments, and automate tasks fast.
How to Start a New .NET Project in 2026: A Beginner's Friendly Guide
A warm, step-by-step guide to starting a new .NET 10 project in 2026 with the dotnet CLI, the right template, and good folder habits from day one.