Por que o Path.Combine quebra URLs e como corrigir isso?
Imagine: você está escrevendo um aplicativo em C# que acessa uma API. Você precisa montar uma URL como https://api.example.com/v1/users/123. A primeira coisa que vem à mente é usar o conhecido Path.Combine. E isso é um erro que milhares de desenvolvedores cometem. A pergunta «Path.Combine for URLs?» no Stack Overflow acumulou centenas de milhares de visualizações — e não é à toa.
Neste artigo, vamos analisar por que o Path.Combine é mortalmente perigoso para URLs e mostrar 4 maneiras corretas de unir endereços em C#. Você aprenderá como funciona o UriBuilder, por que vale a pena considerar a biblioteca Flurl e como escrever seu próprio método seguro de união de URLs. Vamos lá!
O problema: o que há de errado com o Path.Combine?
O método Path.Combine foi criado para sistemas de arquivos do Windows. Ele usa a barra invertida (\\) e leva em conta as particularidades dos discos (por exemplo, C:\\). Já a URL funciona com a barra normal (/) e não tem o conceito de "disco". Vejamos um exemplo:
string baseUrl = "https://api.example.com/api";string endpoint = "/users/123";string result = Path.Combine(baseUrl, endpoint);Console.WriteLine(result);// Saída: https:\\\\api.example.com\\api\\users\\123 (no Windows)// Ou pior: https://api.example.com/api/users/123 (se tiver sorte)O resultado, para dizer o mínimo, é inválido. O Path.Combine substitui as barras normais por invertidas (no Windows), e sua requisição HTTP falhará com erro. Mesmo que no Linux pareça normal, o código se torna não portável. E se a URL base já tiver uma barra no final? Ou se o endpoint tiver uma barra dupla? Começa o caos.
Exemplo real do Stack Overflow
Uma das respostas mais populares para a pergunta «Path.Combine for URLs?» (autor — Brian, 600+ votos positivos) começa com a frase: «Por favor, não façam isso. Path.Combine é para arquivos, não para URLs». E essa é a regra de ouro. Vamos entender quais ferramentas o C# oferece para trabalhar com URLs de forma segura.
Método 1: Uri.TryCreate — método nativo do .NET
A primeira e mais óbvia maneira é usar a classe Uri. Ela sabe unir corretamente a URL base e o caminho relativo:
string baseUrl = "https://api.example.com/api";string relativePath = "/users/123";
if (Uri.TryCreate(baseUrl, relativePath, out Uri result)){ Console.WriteLine(result.ToString()); // Saída: https://api.example.com/users/123}else{ Console.WriteLine("URL inválida");}Importante: o segundo argumento do TryCreate deve ser um URI relativo (começar com /). Se você passar apenas "users/123", ele será interpretado como absoluto — e o resultado será incorreto. Não é o método mais flexível, mas para casos simples é uma excelente solução nativa.
Método 2: UriBuilder — poderoso e flexível
A classe UriBuilder oferece controle total sobre cada parte da URL: esquema, host, porta, caminho e parâmetros de consulta. É a escolha ideal quando você precisa montar um endereço complexo:
var builder = new UriBuilder("https://api.example.com");builder.Port = 8080;builder.Path = "/api/v1/users";builder.Query = "page=1&limit=10";
Uri uri = builder.Uri;Console.WriteLine(uri.ToString());// Saída: https://api.example.com:8080/api/v1/users?page=1&limit=10Por que isso é legal?
- Escapamento automático — caracteres especiais nos parâmetros de consulta serão codificados.
- Barras corretas — o
UriBuilderadiciona ou remove barras extras automaticamente. - Portas e esquemas — fácil mudar de http para https ou adicionar uma porta.
Mas há um detalhe: Path
Blogs
Book Recommendations
Leia também
Removendo uma propriedade de um objeto JavaScript: 3 abordagens e armadilhas
CI/CD para projetos Go: GitHub Actions do A ao Z
Como passar em uma entrevista de PHP: principais perguntas de A a Z
Padrões de Projeto em PHP: exemplos e aplicação
Avisos e Alertas do PHP: como entender e corrigir erros undefined