Suporte a arquivos SLNX no .NET CLI

Os arquivos .slnx são o novo formato de solução do .NET, baseado em XML, e o .NET CLI passou a suportá-los a partir do SDK 9.0.200. Esse formato é uma evolução dos tradicionais arquivos .sln, com uma estrutura mais enxuta, legível e fácil de versionar.

A Microsoft anunciou esse suporte no .NET Blog em março de 2025. Desde então, você consegue criar, migrar e manipular soluções direto pela linha de comando, sem depender do Visual Studio.

Neste artigo, você vai entender por que o formato surgiu, como migrar uma solução existente e quais cuidados tomar durante a transição.

O que são os arquivos .slnx

Uma solução agrupa vários projetos .NET em uma única unidade de trabalho. Por exemplo, ela pode reunir uma API, uma biblioteca de domínio e um projeto de testes.

Durante décadas, essa função ficou com o arquivo .sln. Agora, os arquivos .slnx assumem o mesmo papel com uma sintaxe XML simples, parecida com a dos arquivos .csproj que você já conhece.

Na prática, um arquivo .slnx lista os projetos, as plataformas de build e, quando necessário, as pastas da solução. Tudo isso em poucas linhas, sem GUIDs repetidos nem seções globais extensas.

Para ler e gravar os dois formatos, a Microsoft publicou a biblioteca open source Microsoft.VisualStudio.SolutionPersistence. Assim, o Visual Studio, o MSBuild e o .NET CLI usam o mesmo código para interpretar soluções.

Por que os arquivos .slnx foram criados

O formato .sln existe há décadas e continua essencial para gerenciar vários projetos no Visual Studio. No entanto, ele apresenta algumas limitações conhecidas.

Pouca legibilidade

O .sln é um arquivo de texto com uma sintaxe proprietária, cheia de GUIDs e seções como GlobalSection. Por isso, editá-lo manualmente é trabalhoso e propenso a erros.

Cada projeto aparece com um GUID de tipo, um GUID próprio e várias linhas de configuração para cada combinação de plataforma. Com isso, uma solução média facilmente passa de centenas de linhas.

Conflitos no versionamento

Como a estrutura do .sln repete informações em vários pontos, lidar com conflitos de merge no Git é desafiador. Quando duas pessoas adicionam projetos ao mesmo tempo, as alterações se misturam em blocos diferentes do arquivo.

Se você ainda está se familiarizando com o controle de versão, o artigo sobre Git e GitHub: instalação, configuração e primeiros passos ajuda a entender por que arquivos menores e mais previsíveis geram menos conflitos.

Foco no Visual Studio

O .sln nasceu para o Visual Studio. Embora o comando dotnet sln já existisse para manipulá-lo, o formato nunca foi pensado para edição fora da IDE.

Com os arquivos .slnx, a Microsoft resolveu esses pontos ao adotar XML, um formato que facilita a leitura, a edição e o versionamento. Além disso, ela levou o suporte completo para o .NET CLI.

Suporte a arquivos .slnx no .NET CLI

Segundo o anúncio oficial no .NET Blog, o SDK 9.0.200 trouxe suporte aos arquivos .slnx nos principais comandos do CLI. Entre eles estão dotnet sln migrate, dotnet sln add, dotnet sln remove, dotnet sln list e dotnet build.

O MSBuild também passou a entender o formato a partir da versão 17.13. Por isso, comandos como dotnet build e dotnet test funcionam com a solução nova sem nenhuma configuração extra.

Para conferir qual SDK você tem instalado, rode o comando abaixo:

dotnet --version

Se a versão for inferior a 9.0.200, atualize o SDK antes de seguir. Caso contrário, os comandos com arquivos .slnx vão falhar.

Criando uma solução .sln

No .NET 9, o template de solução ainda gera o formato antigo. Para criar uma solução, basta executar o seguinte comando:

dotnet new sln -n MySolution

Esse comando cria um arquivo MySolution.sln com a estrutura tradicional. Depois de adicionar um projeto de console, o conteúdo fica parecido com este:

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SolutionX.Console", "SolutionX.Console\SolutionX.Console.csproj", "{3EE8F8FD-FFF5-4553-9086-2AD2FF4D63C2}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Debug|x64 = Debug|x64
		Debug|x86 = Debug|x86
		Release|Any CPU = Release|Any CPU
		Release|x64 = Release|x64
		Release|x86 = Release|x86
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{3EE8F8FD-FFF5-4553-9086-2AD2FF4D63C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{3EE8F8FD-FFF5-4553-9086-2AD2FF4D63C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{3EE8F8FD-FFF5-4553-9086-2AD2FF4D63C2}.Debug|x64.ActiveCfg = Debug|Any CPU
		{3EE8F8FD-FFF5-4553-9086-2AD2FF4D63C2}.Debug|x64.Build.0 = Debug|Any CPU
		{3EE8F8FD-FFF5-4553-9086-2AD2FF4D63C2}.Debug|x86.ActiveCfg = Debug|Any CPU
		{3EE8F8FD-FFF5-4553-9086-2AD2FF4D63C2}.Debug|x86.Build.0 = Debug|Any CPU
		{3EE8F8FD-FFF5-4553-9086-2AD2FF4D63C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{3EE8F8FD-FFF5-4553-9086-2AD2FF4D63C2}.Release|Any CPU.Build.0 = Release|Any CPU
		{3EE8F8FD-FFF5-4553-9086-2AD2FF4D63C2}.Release|x64.ActiveCfg = Release|Any CPU
		{3EE8F8FD-FFF5-4553-9086-2AD2FF4D63C2}.Release|x64.Build.0 = Release|Any CPU
		{3EE8F8FD-FFF5-4553-9086-2AD2FF4D63C2}.Release|x86.ActiveCfg = Release|Any CPU
		{3EE8F8FD-FFF5-4553-9086-2AD2FF4D63C2}.Release|x86.Build.0 = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
EndGlobal

Repare que um único projeto já gera mais de 30 linhas. Além disso, o mesmo GUID aparece doze vezes, uma para cada combinação de configuração e plataforma.

Como migrar para arquivos .slnx

Para converter uma solução existente, use o comando dotnet sln migrate:

dotnet sln migrate

Quando você não informa o arquivo, o comando procura um .sln na pasta atual. Se houver mais de um, ele pede que você indique qual usar:

dotnet sln MySolution.sln migrate

Como resultado, você ganha um arquivo bem mais enxuto:

<Solution>
  <Configurations>
    <Platform Name="Any CPU" />
    <Platform Name="x64" />
    <Platform Name="x86" />
  </Configurations>
  <Project Path="SolutionX.Console/SolutionX.Console.csproj" />
</Solution>

As mais de 30 linhas viraram oito. Ou seja, o arquivo agora mostra apenas o que importa: as plataformas e o caminho de cada projeto.

Vale notar que o comando não apaga o .sln original. Ele apenas gera o .slnx ao lado, e a decisão de remover o arquivo antigo fica com você.

Segundo a documentação do comando dotnet sln, a migração falha se já existir um .slnx com o mesmo nome na pasta. O mesmo acontece se você passar um .slnx como entrada, em vez de um .sln.

Entendendo a estrutura dos arquivos .slnx

O XML gerado pela migração tem poucos elementos, e cada um tem uma função clara. Por isso, vale conhecer cada um antes de editar o arquivo à mão.

O elemento raiz é o Solution, que envolve todo o conteúdo. Dentro dele, o bloco Configurations lista as plataformas de build com elementos Platform, como Any CPU, x64 e x86.

Em seguida, cada projeto aparece em um elemento Project com o atributo Path. Esse caminho é relativo à pasta da solução e usa barras normais, o que funciona bem em Windows, Linux e macOS.

Repare também no que não aparece mais. O .slnx não guarda GUIDs de projeto nem repete a matriz de configurações para cada projeto.

Com isso, o arquivo registra apenas o que difere do comportamento padrão.

Na prática, isso significa que uma revisão de código mostra exatamente o que mudou. Quando alguém adiciona um projeto, o diff exibe uma única linha nova, em vez de dezenas de linhas espalhadas.

Gerenciando projetos em arquivos .slnx

Depois da migração, os comandos do dia a dia continuam os mesmos. A única diferença é o arquivo que você informa.

Adicionando e removendo projetos

Para criar um projeto de console e adicioná-lo à solução, use:

dotnet new console -o MyConsoleApp
dotnet sln MySolution.slnx add MyConsoleApp

Da mesma forma, para remover o projeto da solução, troque add por remove:

dotnet sln MySolution.slnx remove MyConsoleApp

O CLI mantém automaticamente os metadados e a estrutura organizacional dos projetos dentro da solução. Assim, você não precisa editar o XML à mão para tarefas comuns.

Organizando em pastas de solução

Em soluções maiores, é comum agrupar projetos em pastas virtuais. Para isso, o comando dotnet sln add aceita a opção --solution-folder:

dotnet sln MySolution.slnx add --solution-folder src MyConsoleApp

No arquivo XML, essas pastas aparecem como elementos Folder, com os projetos aninhados dentro deles. Dessa forma, a hierarquia que você vê no Solution Explorer fica explícita no próprio arquivo.

Listando projetos

Para listar todos os projetos presentes na solução, rode:

dotnet sln MySolution.slnx list

Esse comando é útil em scripts, porque devolve os caminhos de cada projeto em texto simples.

Compilando a solução

Por fim, para compilar todos os projetos da solução, basta rodar:

dotnet build MySolution.slnx

O mesmo vale para dotnet test, que executa todos os projetos de teste referenciados no arquivo.

Cuidados na transição para arquivos .slnx

A migração é simples, mas alguns detalhes podem causar surpresas. Por isso, vale conhecer os pontos de atenção antes de mudar o repositório inteiro.

Valide a migração antes de remover o .sln

Antes de apagar o arquivo antigo, compare as duas versões. Uma forma simples é listar os projetos de cada uma e conferir se o resultado é o mesmo:

dotnet sln MySolution.sln list
dotnet sln MySolution.slnx list

Depois disso, rode dotnet build e dotnet test apontando para o .slnx. Se tudo compilar e os testes passarem, você tem uma boa indicação de que a migração preservou a solução.

Garanta a mesma versão do SDK no time

Os arquivos .slnx só funcionam no CLI a partir do SDK 9.0.200. Assim, se alguém do time ainda usa um SDK anterior, os comandos vão falhar na máquina dessa pessoa.

Para evitar esse problema, combine com a equipe a versão mínima do SDK. Um arquivo global.json na raiz do repositório ajuda a fixar essa versão para todos, inclusive no servidor de CI.

Não deixe .sln e .slnx juntos

O anúncio oficial alerta que é um erro rodar dotnet build ou outros comandos em uma pasta que tenha um .sln e um .slnx ao mesmo tempo. Nesse caso, o CLI não sabe qual arquivo usar.

Portanto, ou você informa o arquivo explicitamente em cada comando, ou remove o .sln depois de validar a migração. Na maioria dos projetos, a segunda opção é a mais segura.

Atualize scripts e pipelines

Scripts de build e pipelines de CI costumam apontar para o arquivo .sln pelo nome. Assim, depois da migração, eles precisam passar a usar o .slnx.

Se você usa GitHub Actions, revise cada passo que chama dotnet restore, dotnet build ou dotnet test. O artigo sobre workflows reutilizáveis no GitHub Actions mostra como centralizar esses comandos e evitar a mesma alteração em vários arquivos.

Confira o suporte das ferramentas

Na época do anúncio, o suporte das ferramentas ainda estava amadurecendo. No Visual Studio, o recurso exigia a opção de preview "Use Solution File Persistence Model" e ficou disponível de forma geral na versão 17.14.

O C# Dev Kit, por sua vez, exigia a configuração dotnet.defaultSolution para abrir os arquivos .slnx. Se você usa o editor da Microsoft, o artigo sobre instalação e customização do Visual Studio Code ajuda a preparar o ambiente.

Já o JetBrains Rider tinha suporte preliminar. Além disso, alguns comandos, como dotnet list package, só passaram a aceitar o formato no SDK 9.0.201.

Principais vantagens dos arquivos .slnx

Depois de ver o formato na prática, fica mais fácil resumir os ganhos:

  1. Formato legível: o XML facilita a leitura, a edição e o versionamento do arquivo.
  2. Integração com o .NET CLI: você gerencia soluções sem depender do Visual Studio.
  3. Flexibilidade: o formato lida melhor com soluções grandes e complexas.
  4. Automação: scripts e ferramentas externas manipulam o arquivo com facilidade, inclusive pela biblioteca Microsoft.VisualStudio.SolutionPersistence.
  5. Menos conflitos: como cada projeto ocupa uma linha, os merges no Git ficam mais simples.

Quando migrar para arquivos .slnx

Nem todo projeto precisa migrar no mesmo dia. Em geral, a decisão depende das ferramentas que o time usa e da frequência com que a solução muda.

Projetos novos são os candidatos mais óbvios, porque não têm histórico nem pipelines antigos para ajustar. Da mesma forma, repositórios com muitos projetos e conflitos frequentes no .sln ganham bastante com a troca.

Por outro lado, se parte da equipe usa uma IDE ou ferramenta que ainda não lê o formato, vale esperar. Nesse cenário, manter o .sln evita bloquear o trabalho de quem depende dele.

Uma boa estratégia é migrar primeiro em um branch e pedir que cada pessoa abra a solução no próprio ambiente. Então, depois de confirmar que todos conseguem compilar e depurar, você integra a mudança e remove o arquivo antigo.

Impacto para desenvolvedores

Essa mudança traz um impacto significativo para quem usa o .NET CLI fora do Visual Studio, como em Linux e macOS. Afinal, editar e revisar a solução deixa de exigir uma IDE.

Ela também beneficia equipes que mantêm grandes soluções em repositórios Git. Com arquivos menores, as revisões de pull request ficam mais claras e os conflitos diminuem.

Além disso, a Microsoft deixou claro que aposta no novo formato. No .NET 10, o comando dotnet new sln passou a gerar arquivos .slnx por padrão, e quem precisar do formato antigo pode usar a opção --format sln.

Conclusão

O suporte aos arquivos .slnx no .NET CLI é um grande avanço para a plataforma, porque torna o gerenciamento de soluções mais moderno e eficiente.

Com um formato baseado em XML e integração completa com a linha de comando, o novo arquivo simplifica o desenvolvimento, facilita a automação e melhora a experiência de times com projetos grandes.

Se você ainda não experimentou, vale testar em um branch separado com dotnet sln migrate. Em seguida, valide o build, atualize os pipelines e remova o .sln antigo.

FAQ

Qual versão do SDK suporta arquivos .slnx?

O .NET CLI passou a suportar o formato a partir do SDK 9.0.200. Alguns comandos, como dotnet list package, só ganharam suporte no 9.0.201.

O dotnet sln migrate apaga o arquivo .sln?

Não, o comando apenas gera o .slnx ao lado do arquivo original. Depois de validar a migração, você mesmo remove o .sln.

Posso manter o .sln e o .slnx na mesma pasta?

Pode, mas os comandos do CLI vão exigir que você informe qual arquivo usar. Sem isso, rodar dotnet build na pasta gera erro.

O formato .slnx usa JSON ou XML?

O formato usa XML, com uma sintaxe parecida com a dos arquivos .csproj. Isso facilita a leitura por pessoas e por ferramentas.

O Visual Studio abre arquivos .slnx?

Sim, o suporte ficou disponível de forma geral no Visual Studio 17.14. Em versões anteriores, era preciso ativar a opção de preview "Use Solution File Persistence Model".