Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
155625 stories
·
33 followers

Exploring the SLNX Solution File Format

1 Share

SLNX files are here! In this post, we'll talk about what this format is, why it exists, what it gets right and where you might get tripped up.

If you’ve worked with .NET for any length of time, you’ve made peace with the .sln file. Not because it’s good (it isn’t) but because it’s the format we have. It’s verbose, GUID-laden and a reliable source of merge conflicts on Friday afternoons. It’s the format we tolerate, not the one we’d choose.

The good news is there’s a new format in town. The .slnx format is Microsoft’s XML-based replacement for the venerable .sln file, and it has been steadily gaining first-class support across Visual Studio, the .NET CLI, MSBuild and Rider over the last year. As of .NET 9.0.200 and Visual Studio 17.13+, you can use it for real projects without crossing your fingers. And as of .NET 10, dotnet new sln defaults to .slnx.

In this post, let’s talk about what .slnx is, why it exists, what it gets right and where you might get tripped up.

A Quick SLN Retrospective

To appreciate why we’re getting a new format, let’s remember what we’ve been working with. Here’s a typical fragment of an .sln file.

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.10.34804.81
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyApi", "MyApi\MyApi.csproj", "{F95781B3-A973-4D19-9585-974DA143E6A1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8FC526EA-218B-4615-8410-4E1850611F38}"
ProjectSection(SolutionItems) = preProject
Directory.Build.props = Directory.Build.props
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F95781B3-A973-4D19-9585-974DA143E6A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F95781B3-A973-4D19-9585-974DA143E6A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F95781B3-A973-4D19-9585-974DA143E6A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F95781B3-A973-4D19-9585-974DA143E6A1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

Oof. The SLN format is a custom Microsoft format that has some weird quirks. Every project gets a GUID. Solution folders are themselves projects with their own GUIDs. Configuration combinations even get cross-multiplied so a four-project solution with two configurations and two platforms produces 16 lines of nearly identical setup.

The pain points are well known to us all. If even two developers add a project at the same time, both edit GlobalSection(ProjectConfigurationPlatforms), and Git throws its hands up.

GUIDs, bless their hearts, are not for human eyes. It’s a nightmare trying to figure out which project owns which configuration block. And outside of Visual Studio, generating or modifying .sln files reliably often requires a tool like slngen because no one wants to write the parser themselves.

This is what the .slnx tries to fix.

Looking Inside the .slnx

Here’s the same project, but expressed as .slnx.

<Solution>
  <Folder Name="/Solution Items/">
    <File Path="Directory.Build.props" />
  </Folder>
  <Project Path="MyApi/MyApi.csproj" />
</Solution>

Notice how we have no GUIDs, no cross-multiplied configuration table and no EndGlobalSection markers. Even a developer who is foreign to the .slnx format can read it and immediately understand it.

Expanding a little, here’s an example from a layered solution.

<Solution>
  <Folder Name="/Solution Items/">
    <File Path=".editorconfig" />
    <File Path="Directory.Build.props" />
    <File Path="Directory.Packages.props" />
  </Folder>
  <Folder Name="/src/">
    <Project Path="src/Application/Application.csproj" />
    <Project Path="src/Domain/Domain.csproj" />
    <Project Path="src/Infrastructure/Infrastructure.csproj" />
    <Project Path="src/Web.Api/Web.Api.csproj" />
  </Folder>
  <Folder Name="/tests/">
    <Project Path="tests/UnitTests/UnitTests.csproj" />
    <Project Path="tests/IntegrationTests/IntegrationTests.csproj" />
  </Folder>
</Solution>

If you compare this to the equivalent .sln, you’re looking at maybe a third of the lines, with none of the GUID overhead. If you need to override configurations for a specific project (like, say your test project shouldn’t build in Release mode) you can express that with a Configurations element on the project. In reality, most projects won’t need it at all. If you do, you can review examples in microsoft/vs-solutionpersistence and its samples wiki.

If the .slnx looks similar to a .csproj, that’s intentional. Microsoft’s reasoning is that XML is already the format the rest of MSBuild speaks, the team already had a parser for it, and features like comments and attributes are first-class citizens. A JSON or YAML format might have been trendier, but it would have forced the team to invent semantics for things .csproj already has solved problems for.

Migrating Existing Projects

Existing projects are a different conversation. Here’s what you get by migrating, and how to do it cleanly.

  • Merge conflicts are more manageable. Because there are no GUIDs that change every time you touch a project, the diffs you see in PRs are meaningful. If you add a project, you see one line added. Move a project to a different folder, and you see the path change. Nobody has to play GUID detective.
  • You can reasonably edit by hand. You’ll never want to hand-edit a .sln unless it’s an emergency. With .slnx, opening it in your editor of choice is perfectly reasonable. I’ve fixed broken solution layouts in a text editor faster than Visual Studio would have let me click through the dialogs.
  • Tooling has standardized what a solution is. Microsoft has open-sourced the parser as the Microsoft.VisualStudio.SolutionPersistence NuGet package. This means MSBuild, the .NET CLI and third-party tools are all reading the same file the same way.

Based on the official dotnet sln reference, the actual conversion is one command.

dotnet sln migrate

If you run this in a directory with an .sln file, you’ll get an .slnx file beside it. From Visual Studio, you can also use File -> Save Solution As… and pick XML Solution File (.slnx) from the dropdown. Rider supports a similar flow.

You don’t want to keep both files in the repository. The dotnet sln commands don’t reliably pick the right one when you have both, and it’s easy for the two to get out of sync as people add or remove projects. Pick when to cut over, delete the old file and move on. While there is a community tool called dotnet-sln-sync that helps, that should only be used temporarily and not long term.

As you convert over, here’s a quick checklist to avoid any headaches:

  • Verify your global.json allows the right SDK. You need at least .NET 9.0.200 for full CLI support. If your global.json pins to something older, the migrate command won’t work.
  • Check your CI build agents. If you’re on self-hosted Azure DevOps agents, for example, confirm they’re running an SDK new enough to handle .slnx.
  • Audit your pipelines. Anywhere you have references directly to .sln, update the path. Wildcard references like **/*.sln will miss the new file. If you are using templates where you have a mix of .sln and .slnx, a pattern like **/*.sln* will be useful.
  • Look out for dependent tools. Tools like slngen don’t yet support .slnx at the time of this post (you can track the issue here). If you’re reliant on a tool outside of the Microsoft umbrella, check before you migrate.

Some Rough Edges

The .slnx format is no longer “preview” in any practical sense, but the ecosystem around it is still catching up.

  • Visual Studio file association. Double-clicking a .slnx file doesn’t open Visual Studio by default. You can fix this with a file association or just open it from inside the IDE.
  • C# Dev Kit in VS Code. It works, but you may need to set dotnet.defaultSolution to the path of your .slnx if it isn’t auto-detected.
  • Globbing. You can’t write <Project Path="src/**/*.csproj" /> and have it discover projects automatically. The team’s reasoning, captured in the globbing feature request, is that globbing slows down solution loading on large repos because Visual Studio has to scan the file system before it can render anything. That makes sense, but I think plenty of us would happily trade a slower cold load for never having to add another project entry by hand.
  • Third-party tools. Anything that parses .sln directly needs to update. Hopefully the open-source parser library accelerates that, but you’ll find holdouts.

None of these are dealbreakers for new projects. For older codebases with a lot of tooling baked in, it’s worth doing a small pilot before flipping the whole repo.

Wrapping Up

The .slnx format isn’t a revolutionary feature. It doesn’t change how you write code, it doesn’t add new build capabilities, and it doesn’t speed up your application. It is, however, one of those quality-of-life upgrades that quietly results in fewer merge conflicts, less time staring at GUIDs, less friction in your CI pipelines once they’re set up.

If you’re starting a new .NET solution, just use .slnx from day one. And with .NET 10, you’ll get it without lifting a finger. If you’re maintaining an existing .sln file, plan a migration when you have a slow week, audit your tooling and cut over cleanly. The format isn’t going anywhere, and getting ahead of the transition is easier than waiting for some downstream tool to force your hand.

Thanks for reading, and happy coding!

Further Reading

Read the whole story
alvinashcraft
just a second ago
reply
Pennsylvania, USA
Share this story
Delete

Some Reflections on JasperFx’s 3rd Anniversary

1 Share

I “officially” went solo with JasperFx Software in June of 2023 at the tender age of 49 because hopefully I’m a late bloomer. I’d of course been planning that specific move for quite some time and idly dreaming of being able to found my own company around my OSS passion projects for decades before that. I’ll be writing up something much more official in the JasperFx Software website next year for our 3rd Anniversary as we also officially launch our CritterWatch commercial tool next week, but I felt like jotting down some personal reflections as I wait on a bevy of CI runs to hopefully turn green.

I’ve stumbled around in my career from “real” engineering (petrochemical plants) to “Shadow IT” to kind of doing skunkworks type work in a huge company before fleeing their attempts to do CMMi and off to a high flying Extreme Programming consultancy. Since then its been a mixed bag of small to medium sized companies either doing consulting or product development. I’ve almost always been either a technical lead or architect or even some kind of “Director of Software Architecture,” but almost never felt particularly invested in my job.

I realized early on that I was always much more passionate about my personal work in whatever OSS development tool I was working on at the time. To that end, I’ve long known that I wanted a job building development tooling but it never quite worked out for me to land with a company that did that. My first big attempt at a big OSS tool for other devs that I thought could lead to eventual opportunities (FubuMVC) was a failure so bad that it put me in a multi-year funk. I’ve also been severely limited by being extremely risk averse, so I never had the guts (or wherewithal) to go solo and make the bet on myself and my portfolio of OSS tools.

I will say though that my times where I was actively mentoring other technical leads or architects was very enjoyable. I should say to anybody that I worked with that sees this that I genuinely enjoyed trying to be a mentor at a couple stops when you had to deal with me as the architecture team lead:) But again, that plays into the theme of “wanting to feel respected” that I didn’t realize was a thing for me until the past decade.

But anyway, flash foward a couple years, and Marten was becoming undeniably capable and successful. A few interactions with other people convinced me that there was a genuine professional opportunity there. At the same time, my previous job was clearly going South as we got all new C-level management from the outside. I fortunately had a once in a lifetime personal opportunity to try to do my own company instead. So here I am, three years into having my own company.

Our new CTO at the time told me directly not to come to a big meeting in our Dallas office because I wouldn’t add any value after I had asked to be involved specifically to meet him in person for the first time. Ouch. I might send him a little thank you note after this for helping give me an unintentional shove into what I really wanted to be doing in the first place!

The big takeaways for me are that I’m working harder than I ever have, but I love what I do most of the time. I especially love getting to roll out of bed knowing that I’m working on my tools and my vision every day — even when I’m helping clients. One other thing I very much appreciate is that JasperFx clients have specifically sought out my company because they wanted me to be involved and respect what I bring to the table. After a long career of not always feeling exactly respected and valued by management types, that’s turned out to be a very positive thing for me.

I’m constantly frustrated as hell at how long everything has taken to get rolling and that certain products still aren’t perfectly out, but also occasionally amazed at how much has gotten done and what the company has been able to achieve if you flip to the glass half full view of things.

The downsides are just that it’s a tremendous amount of stress, I get exhausted from the overhead of having a business, always being worried about where the next clients and the next work is going to come from, and never really feeling comfortable. And of course, I’m an American and our health care system is awful, so the health insurance angle is frequently stressful as it has limited my wife’s career options a little bit now that I don’t have company sponsored health insurance.



Read the whole story
alvinashcraft
just a second ago
reply
Pennsylvania, USA
Share this story
Delete

AI Splits the Market

1 Share

Most predictions about the AI era assume one outcome across the whole software industry. Startups will eat incumbents. Greenfield will replace brownfield. Faster building means faster disruption. I don't think any of that is true uniformly. The same technology cuts in opposite directions depending on which market it lands in.

A recent NBER working paper by Mert Demirer, Leon Musolff, and Liyuan Yang, Writing Code vs. Shipping Code, tracked over 100,000 GitHub developers from 2022 through 2026 and found that sync agents increased lines of code by 741% and pull requests by 65%, while shipped releases moved only 20% and end-user downloads barely moved at all. The gain shrinks at every step from keystroke to user.

This speaks to a question I raised when DeepSeek's cheaper training run sent NVIDIA stock sideways and Satya pointed to Jevons paradox as the reason not to panic. I think the answer is split. Jevons holds for compute and for lines of code written. It fails for finished applications competing for human attention. The app stores show more supply, flat downloads, and a growing share of apps with effectively zero audience.

Which raises the question, if supply is up and consumer demand is flat, where is this 741% increase in code actually going? I think eventually it will end up in enterprise scenarios, starting with backlogs.

Every organization I have ever worked with curates a queue of deferred work that has been growing for years, filled with low and medium-priority bugs, unfunded accessibility audits, and internal tools that everyone needs but no team owns. None of those items ever shipped because the math did not work, not because the demand was missing. Now the cost side of that math has moved. Work that could not justify a developer-week three years ago can justify an agent-hour today, which is also why the ruthless prioritization I argued for matters less than it did. When the cost of saying yes collapses, the discipline of saying no loses its edge.

Consumer markets favor the startup. Switching costs are low, distribution runs on attention rather than procurement, and novelty can win. AI shortens the build cycle without changing any of that, so the startup advantage only gets sharper.

Enterprise is the opposite. The constraint there has never been the speed of building, it has been integration, compliance, sales cycles, data residency, audit trails, and the long tail of trust that might take a decade or more to accumulate. AI does not compress any of those. What it certainly does compress is the cost of working down an existing backlog, and the organization with the backlog is, by definition, the incumbent. The same technology that lets a startup ship a polished consumer app in a weekend also lets a fifteen-year-old enterprise vendor finally close the tickets they have been deferring since 2014.

If this split holds, AI will be a productivity shift, not a platform shift. Platform shifts (cloud, mobile, SaaS) created openings for new enterprise winners. Productivity shifts accrue to whoever already owns the category. The incumbents do not have to win. They just have to not lose.

The consumer race will be loud and visible. The enterprise race will be slower, less photogenic, and probably more durable. Enterprise is where the value will accrue, even as the consumer space gets all the attention.

Side view of a red Hamburg Süd container ship at port, fully loaded with stacked shipping containers from Maersk, Hamburg Süd, MSC, Sealand, and Safmarine. A white port crane reaches above the ship against a clear blue sky.
Read the whole story
alvinashcraft
15 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

Daily Reading List – June 11, 2026 (#803)

1 Share

I think every one of my dozen meetings today was in a different room (and floor) in the office. That’s not a brag, although my step count today is outstanding.

[article] Your AI strategy has a trust problem, not a tooling problem. Terrific post. Most corporate structures are designed to slow you down, not speed you up. That’s on purpose. Making the needed changes is hard.

[blog] How to unlock true ROI in software development – a deep dive into the latest DORA research. Three good insights here. If you’re struggling to define ROI or you’re in the trough of high cost with no return, read this.

[blog] Loop Engineering. It’s the hot topic this week. No doubt it has a place in certain scenarios. I’m not sold (or want to be sold) that this is how engineering should be moving forward.

[article] Loop Engineering: Design the System That Prompts Agents. Got it. I wonder how “big” a loop should be. If we’re talking small PR-style loops, maybe. If we’re talking entire software construction kicked off by a user-defined “goal”, that seems non-serious to me.

[aricle] The Anthropic leader who built Claude Code says he ditched prompting — now he just writes loops. Last one specifically about loops, I promise. But it’s good to know what the discussion is all about.

[blog] How Gemini Managed Agents Works under the Hood. This is an implementation of loop engineering! You ask for something, and kick off a background process where your intent is turned into a plan that an agent loops on until completion.

[article] Employees spend more time managing AI than producing work. Makes sense. The work is changing. That doesn’t mean the current state is the permanent one.

[article] Engineering leadership lessons from LDX3 2026. Read some takeaways on newly-amplified friction, hiring, and management changes.

[blog] Report: GKE Inference Gateway delivers up to 92% faster AI responses. No comparison if you want fast inference on a cloud Kubernetes. I mean, there is a comparison, and it’s included here. But there’s a clear winner.

[article] AI teams now deploy 1,000 times a month. Your pipeline wasn’t built for that. If your pipelines aren’t groaning right now, and you’re doing a lot of AI-generated code, that’s a concern.

[blog] How to deploy a Google Agent Development Kit (ADK) agent to Google Cloud Run. Nice step-by-step. You can go from nothing to running agent pretty quickly.

[blog] The Unbundling and Bundling of the PaaS Market. Is PaaS back? It’s always a back and forth between independent services and opinionated stack bundles.

[blog] Growing the next generation of American workers. It’s the builder era, and that includes ALL types of builders. Love this investment.

Want to get this update sent to you every day? Subscribe to my RSS feed or subscribe via email below:



Read the whole story
alvinashcraft
44 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

June Patches for Azure DevOps Server

1 Share

We are releasing new patches for our self‑hosted product, Azure DevOps Server. We strongly recommend that all customers stay up to date with the latest, most secure version of Azure DevOps Server.

The most recent release, Azure DevOps Server, is available on the download page.

The following versions have been patched. For more details on these updates, see the release notes:

⬇Azure DevOps Server Patch Download

Version Patch Download Release Notes
Azure DevOps Server Download Patch 5 Release notes
Azure DevOps Server 2022.2 Download Patch 10 Release notes

✅Verifying Installation

To verify that the patch is installed, run the following command on the Azure DevOps Server machine using the patch installer you downloaded:

<patch-installer>.exe CheckInstall

Replace <patch-installer> with the name of the patch file you downloaded. The command output will indicate whether the patch is installed.

The post June Patches for Azure DevOps Server appeared first on Azure DevOps Blog.

Read the whole story
alvinashcraft
49 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

Governing agent autonomy with Auto-review

1 Share
Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories