Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Azure DevOps Services | Azure DevOps Server | Azure DevOps Server 2022
Aviso
Tecnologia herdada - alternativas modernas recomendadas
Esses clientes baseados em SOAP são tecnologia herdada e só devem ser usados para:
- Manter aplicativos existentes que não podem ser modernizados
- Aplicativos do .NET Framework que exigem funcionalidade específica de SOAP
Para desenvolvimento novo, use as bibliotecas de clientes .NET modernas baseadas em REST que oferecem:
- ✅ Melhor desempenho e confiabilidade
- ✅ Suporte para .NET Core, .NET 5+ e .NET Framework
- ✅ Métodos de autenticação modernos (identidades gerenciadas, entidades de serviço)
- ✅ Padrões async/await e recursos modernos do C#
- ✅ Desenvolvimento ativo e suporte
Este artigo contém exemplos de integração com o Azure DevOps Server e o Azure DevOps Services usando clientes SOAP herdados. Esses clientes só estão disponíveis na versão do .NET Framework e exigem métodos de autenticação locais ou herdados.
Pré-requisitos e limitações
Requisitos:
- .NET Framework 4.6.1 ou posterior
- Pacotes NuGet herdados
- Ambiente do Windows para suporte ao cliente SOAP
Limitações de :
- ❌ Sem suporte para .NET Core ou .NET 5+
- ❌ Opções de autenticação moderna limitadas
- ❌ Sem padrões assíncronos/de espera
- ❌ Desempenho reduzido em comparação com clientes REST
- ❌ Suporte e atualizações futuros limitados
Pacotes NuGet necessários:
- Microsoft.TeamFoundationServer.ExtendedClient - Clientes SOAP herdados
- Microsoft.TeamFoundationServer.Client – APIs principais do Azure DevOps
- Microsoft.VisualStudio.Services.Client – Conexão e autenticação
- Microsoft.VisualStudio.Services.InteractiveClient – Fluxos de autenticação interativos
Diretrizes de migração
Caminho de migração recomendado
Etapa 1: Avaliar o uso atual
- Identificar a funcionalidade específica de SOAP que seu aplicativo usa
- Determinar se as APIs REST equivalentes estão disponíveis
- Avaliar os requisitos de autenticação
Etapa 2: Planejar a estratégia de migração
- Imediato: atualizar a autenticação para usar PATs ou a ID do Microsoft Entra
- Curto prazo: migrar para clientes baseados em REST mantendo o .NET Framework
- Longo prazo: modernizar para .NET Core/.NET 5+ com clientes REST
Etapa 3: Implementar a migração
- Comece com atualizações de autenticação. Veja os exemplos a seguir.
- Substituir clientes SOAP por equivalentes REST incrementalmente
- Teste minuciosamente antes de implantar em produção
Para obter diretrizes de migração detalhadas, consulte exemplos de biblioteca de clientes do .NET.
Exemplos de cliente SOAP legado
Uso básico do cliente SOAP
Importante
Este exemplo mostra padrões herdados somente para referência. Use exemplos baseados em REST para o novo desenvolvimento.
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.VisualStudio.Services.Common;
using System;
using System.Linq;
/// <summary>
/// Legacy SOAP client example - use REST clients for new development
/// Creates a work item query, runs it, and displays results
/// </summary>
public static class LegacySoapExample
{
public static void ExecuteWorkItemQuery(string collectionUri, string teamProjectName, VssCredentials credentials)
{
try
{
// Create TfsTeamProjectCollection instance with credentials
using (var tpc = new TfsTeamProjectCollection(new Uri(collectionUri), credentials))
{
// Authenticate the connection
tpc.Authenticate();
// Get the WorkItemStore service (SOAP-based)
var workItemStore = tpc.GetService<WorkItemStore>();
// Get the project context
var workItemProject = workItemStore.Projects[teamProjectName];
// Find 'My Queries' folder
var myQueriesFolder = workItemProject.QueryHierarchy
.OfType<QueryFolder>()
.FirstOrDefault(qh => qh.IsPersonal);
if (myQueriesFolder != null)
{
const string queryName = "Legacy SOAP Sample";
// Check if query already exists
var existingQuery = myQueriesFolder
.OfType<QueryDefinition>()
.FirstOrDefault(qi => qi.Name.Equals(queryName, StringComparison.OrdinalIgnoreCase));
QueryDefinition queryDefinition;
if (existingQuery == null)
{
// Create new query with proper WIQL
queryDefinition = new QueryDefinition(
queryName,
@"SELECT [System.Id], [System.WorkItemType], [System.Title],
[System.AssignedTo], [System.State], [System.Tags]
FROM WorkItems
WHERE [System.TeamProject] = @project
AND [System.WorkItemType] = 'Bug'
AND [System.State] = 'New'
ORDER BY [System.CreatedDate] DESC");
myQueriesFolder.Add(queryDefinition);
workItemProject.QueryHierarchy.Save();
}
else
{
queryDefinition = existingQuery;
}
// Execute the query
var workItems = workItemStore.Query(queryDefinition.QueryText);
Console.WriteLine($"Found {workItems.Count} work items:");
foreach (WorkItem workItem in workItems)
{
var title = workItem.Fields["System.Title"].Value;
var state = workItem.Fields["System.State"].Value;
Console.WriteLine($"#{workItem.Id}: {title} [{state}]");
}
if (workItems.Count == 0)
{
Console.WriteLine("No work items found matching the query criteria.");
}
}
else
{
Console.WriteLine("'My Queries' folder not found.");
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error executing SOAP query: {ex.Message}");
throw;
}
}
}
Métodos de autenticação herdados
Aviso
Esses métodos de autenticação têm limitações de segurança. Migre para a autenticação moderna quando possível.
Autenticação de token de acesso pessoal (não recomendado)
/// <summary>
/// Authenticate SOAP client using Personal Access Token
/// Most secure option for legacy SOAP clients
/// </summary>
public static void AuthenticateWithPAT(string collectionUri, string personalAccessToken)
{
try
{
var credentials = new VssBasicCredential(string.Empty, personalAccessToken);
using (var tpc = new TfsTeamProjectCollection(new Uri(collectionUri), credentials))
{
tpc.Authenticate();
Console.WriteLine($"Successfully authenticated to: {tpc.DisplayName}");
Console.WriteLine($"Instance ID: {tpc.InstanceId}");
}
}
catch (Exception ex)
{
Console.WriteLine($"PAT authentication failed: {ex.Message}");
throw;
}
}
Autenticação do Microsoft Entra (suporte limitado)
/// <summary>
/// Microsoft Entra authentication for SOAP services
/// Limited to specific scenarios - prefer REST clients for modern auth
/// </summary>
public static void AuthenticateWithEntraID(string collectionUri)
{
try
{
// Note: Limited authentication options compared to REST clients
var credentials = new VssAadCredential();
using (var tpc = new TfsTeamProjectCollection(new Uri(collectionUri), credentials))
{
tpc.Authenticate();
Console.WriteLine($"Successfully authenticated with Microsoft Entra ID");
Console.WriteLine($"Collection: {tpc.DisplayName}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Microsoft Entra authentication failed: {ex.Message}");
Console.WriteLine("Consider migrating to REST clients for better authentication support.");
throw;
}
}
Autenticação interativa (somente .NET Framework)
/// <summary>
/// Interactive authentication with Visual Studio sign-in prompt
/// Only works in .NET Framework with UI context
/// </summary>
public static void AuthenticateInteractively(string collectionUri)
{
try
{
var credentials = new VssClientCredentials();
using (var tpc = new TfsTeamProjectCollection(new Uri(collectionUri), credentials))
{
tpc.Authenticate();
Console.WriteLine($"Interactive authentication successful");
Console.WriteLine($"Authenticated user: {tpc.AuthorizedIdentity.DisplayName}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Interactive authentication failed: {ex.Message}");
Console.WriteLine("Ensure application has UI context and user interaction is possible.");
throw;
}
}
Autenticação de nome de usuário/senha (preterida)
Cuidado
A autenticação de nome de usuário/senha é preterida e insegura. Em vez disso, use PATs ou métodos de autenticação modernos.
/// <summary>
/// Username/password authentication - DEPRECATED AND INSECURE
/// Only use for legacy on-premises scenarios where no alternatives exist
/// </summary>
[Obsolete("Username/password authentication is deprecated. Use PATs or modern authentication.")]
public static void AuthenticateWithUsernamePassword(string collectionUri, string username, string password)
{
try
{
var credentials = new VssAadCredential(username, password);
using (var tpc = new TfsTeamProjectCollection(new Uri(collectionUri), credentials))
{
tpc.Authenticate();
Console.WriteLine("Username/password authentication successful (DEPRECATED)");
}
}
catch (Exception ex)
{
Console.WriteLine($"Username/password authentication failed: {ex.Message}");
Console.WriteLine("This method is deprecated. Please migrate to PATs or modern authentication.");
throw;
}
}
Exemplo herdado completo
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.VisualStudio.Services.Common;
using System;
using System.Configuration;
/// <summary>
/// Complete example showing legacy SOAP client usage
/// For reference only - use REST clients for new development
/// </summary>
class LegacySoapProgram
{
static void Main(string[] args)
{
try
{
// Get configuration (prefer environment variables or secure config)
var collectionUri = ConfigurationManager.AppSettings["CollectionUri"];
var projectName = ConfigurationManager.AppSettings["ProjectName"];
var personalAccessToken = ConfigurationManager.AppSettings["PAT"]; // Store securely
if (string.IsNullOrEmpty(collectionUri) || string.IsNullOrEmpty(projectName))
{
Console.WriteLine("Please configure CollectionUri and ProjectName in app.config");
return;
}
Console.WriteLine("=== Legacy SOAP Client Example ===");
Console.WriteLine("WARNING: This uses deprecated SOAP clients.");
Console.WriteLine("Consider migrating to REST clients for better performance and support.");
Console.WriteLine();
VssCredentials credentials;
if (!string.IsNullOrEmpty(personalAccessToken))
{
// Recommended: Use PAT authentication
credentials = new VssBasicCredential(string.Empty, personalAccessToken);
Console.WriteLine("Using Personal Access Token authentication");
}
else
{
// Fallback: Interactive authentication (requires UI)
credentials = new VssClientCredentials();
Console.WriteLine("Using interactive authentication");
}
// Execute the legacy SOAP example
LegacySoapExample.ExecuteWorkItemQuery(collectionUri, projectName, credentials);
Console.WriteLine();
Console.WriteLine("Example completed successfully.");
Console.WriteLine("For new development, see: https://docs.microsoft.com/azure/devops/integrate/concepts/dotnet-client-libraries");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
Console.WriteLine();
Console.WriteLine("Migration recommendations:");
Console.WriteLine("1. Update to REST-based client libraries");
Console.WriteLine("2. Use modern authentication (managed identities, service principals)");
Console.WriteLine("3. Migrate to .NET Core/.NET 5+ for better performance");
Environment.Exit(1);
}
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
Migração para aplicativos modernos
Comparação lado a lado
Abordagem SOAP herdada:
// ❌ Legacy SOAP pattern
using (var tpc = new TfsTeamProjectCollection(uri, credentials))
{
var workItemStore = tpc.GetService<WorkItemStore>();
var workItems = workItemStore.Query("SELECT * FROM WorkItems");
// Synchronous, blocking operations
}
Abordagem REST moderna:
// ✅ Modern REST pattern
using var connection = new VssConnection(uri, credentials);
var witClient = connection.GetClient<WorkItemTrackingHttpClient>();
var workItems = await witClient.QueryByWiqlAsync(new Wiql { Query = "SELECT * FROM WorkItems" });
// Asynchronous, non-blocking operations
Principais diferenças
| Característica | SOAP herdado | REST moderno |
|---|---|---|
| Suporte à plataforma | Somente .NET Framework | .NET Framework, .NET Core, .NET 5+ |
| Desempenho | Mais lento, síncrono | Mais rápido, assíncrono |
| Autenticação | Opções limitadas | Suporte completo de autenticação moderna |
| Cobertura de API | Somente APIs herdadas | Cobertura completa da API REST |
| Suporte futuro | Somente manutenção | Desenvolvimento ativo |
| Padrões de código | Bloqueio síncrono | Padrões assíncronos ou de espera |
Solução de problemas de clientes legados
Problemas comuns e soluções
Falhas de autenticação:
- Verifique se os PATs têm escopos apropriados
- Verificar o formato de URL da organização (incluir coleção para ambientes locais)
- Confira as configurações do firewall e do proxy para os pontos de extremidade SOAP
Problemas de desempenho:
- Os clientes SOAP são inerentemente mais lentos que REST
- Considere as operações em lote sempre que possível
- Migrar para clientes REST para melhor desempenho
Compatibilidade da plataforma:
- Os clientes SOAP só funcionam no .NET Framework
- Usar clientes REST para suporte multiplataforma
Obtendo ajuda
Para problemas de cliente SOAP herdado:
- Verificar a Comunidade de Desenvolvedores do Azure DevOps
- Examinar as diretrizes de migração para alternativas modernas
- Considere os serviços de migração profissional para aplicativos grandes
Recursos relacionados
Recursos de migração:
- Exemplos modernos de biblioteca cliente do .NET – Substituição recomendada
- Diretrizes de autenticação – Opções de autenticação modernas
- Referência da API REST do Azure DevOps – Documentação completa da API
Documentação herdada:
Importante
Planejando a migração? Comece com exemplos modernos da biblioteca de clientes do .NET para ver as práticas recomendadas atuais e as opções de autenticação.