Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Azure DevOps Services | Azure DevOps Server | Azure DevOps Server 2022
Warnung
Veraltete Technologie – moderne Alternativen empfohlen
Diese SOAP-basierten Clients sind veraltete Technologie und sollten nur für:
- Verwalten vorhandener Anwendungen, die nicht modernisiert werden können
- .NET Framework-Anwendungen, die SOAP-spezifische Funktionen erfordern
Verwenden Sie für die neue Entwicklung die modernen REST-basierten .NET-Clientbibliotheken , die Folgendes bieten:
- ✅ Bessere Leistung und Zuverlässigkeit
- ✅ Unterstützung für .NET Core, .NET 5+ und .NET Framework
- ✅ Moderne Authentifizierungsmethoden (verwaltete Identitäten, Dienstprinzipale)
- ✅ Async/Await-Muster und moderne C#-Funktionen
- ✅ Aktive Entwicklung und Unterstützung
Dieser Artikel enthält Beispiele für die Integration in Azure DevOps Server und Azure DevOps Services mit älteren SOAP-Clients. Diese Clients sind nur in der .NET Framework-Version verfügbar und erfordern lokale oder ältere Authentifizierungsmethoden.
Voraussetzungen und Einschränkungen
Anforderungen:
- .NET Framework 4.6.1 oder höher
- Legacy-NuGet-Pakete
- Windows-Umgebung für SOAP-Clientunterstützung
Einschränkungen:
- ❌ Keine .NET Core- oder .NET 5+-Unterstützung
- ❌ Eingeschränkte moderne Authentifizierungsoptionen
- ❌ Keine async/await-Muster
- ❌ Reduzierte Leistung im Vergleich zu REST-Clients
- ❌ Eingeschränkter zukünftiger Support und Updates
Erforderliche NuGet-Pakete:
- Microsoft.TeamFoundationServer.ExtendedClient – Ältere SOAP-Clients
- Microsoft.TeamFoundationServer.Client – Kern-Azure DevOps-APIs
- Microsoft.VisualStudio.Services.Client – Verbindung und Authentifizierung
- Microsoft.VisualStudio.Services.InteractiveClient – Interaktive Authentifizierungsflüsse
Migrationsleitfaden
Empfohlener Migrationspfad
Schritt 1: Bewerten Sie Ihre aktuelle Nutzung
- Identifizieren von SOAP-spezifischen Funktionen, die Ihre Anwendung verwendet
- Ermitteln, ob entsprechende REST-APIs verfügbar sind
- Evaluieren von Authentifizierungsanforderungen
Schritt 2: Planen der Migrationsstrategie
- Sofort: Aktualisieren Sie die Authentifizierung, um PATs oder Microsoft Entra-ID zu nutzen.
- Kurzfristig: Migrieren zu REST-basierten Clients, während .NET Framework beibehalten wird
- Langfristig: Modernisieren von .NET Core/.NET 5+ mit REST-Clients
Schritt 3: Implementieren der Migration
- Beginnen Sie mit Authentifizierungsupdates. Sehen Sie sich die folgenden Beispiele an.
- Ersetzen von SOAP-Clients durch REST-Entsprechungen inkrementell
- Testen Sie gründlich, bevor Sie in die Produktionsumgebung bereitstellen.
Ausführliche Anleitungen zur Migration finden Sie unter .NET-Clientbibliotheksbeispiele.
Beispiele für ältere SOAP-Clients
Grundlegende SOAP-Clientverwendung
Von Bedeutung
In diesem Beispiel werden veraltete Muster nur als Referenz gezeigt. Verwenden Sie REST-basierte Beispiele für die neue Entwicklung.
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;
}
}
}
Authentifizierungsmethoden für veraltete Systeme
Warnung
Diese Authentifizierungsmethoden weisen Sicherheitsbeschränkungen auf. Migrieren Sie nach Möglichkeit zur modernen Authentifizierung .
Authentifizierung des persönlichen Zugriffstokens (nicht empfohlen)
/// <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;
}
}
Microsoft Entra-Authentifizierung (eingeschränkter Support)
/// <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;
}
}
Interaktive Authentifizierung (nur.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;
}
}
Authentifizierung mit Benutzername/Kennwort (veraltet)
Vorsicht
Die Authentifizierung mit Benutzername/Kennwort ist veraltet und unsicher. Verwenden Sie stattdessen PATs oder moderne Authentifizierungsmethoden.
/// <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;
}
}
Veraltetes Beispiel abschließen
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();
}
}
Migration zu modernen Clients
Gegenüberstellung
Legacy-SOAP-Ansatz:
// ❌ 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
}
Moderner REST-Ansatz:
// ✅ 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
Wichtige Unterschiede
| Merkmal | Legacy-SOAP | Der moderne REST |
|---|---|---|
| Plattformunterstützung | Nur .NET Framework | .NET Framework, .NET Core, .NET 5+ |
| Leistung | Langsamer, synchron | Schneller, asynchron |
| Authentifizierung | Eingeschränkte Optionen | Vollständiger moderner Support für Autorisierung |
| API-Abdeckung | Nur Ältere APIs | Vollständige REST-API-Abdeckung |
| Zukünftiger Support | Nur Wartung | Aktive Entwicklung |
| Codemuster | Synchrones Blockieren | Async/Wait-Muster strukturieren |
Problembehandlung bei Legacy-Clients
Häufige Probleme und Lösungen
Authentifizierungsfehler:
- Sicherstellen, dass PATs über geeignete Bereiche verfügen
- Überprüfen des URL-Formats der Organisation (einschließlich Collection für on-premises)
- Überprüfen der Firewall- und Proxyeinstellungen für SOAP-Endpunkte
Leistungsprobleme:
- SOAP-Clients sind inhärent langsamer als REST
- Ziehen Sie batchvorgänge nach Möglichkeit in Betracht.
- Migrieren zu REST-Clients zur besseren Leistung
Plattformkompatibilität:
- SOAP-Clients funktionieren nur in .NET Framework
- Verwenden von REST-Clients für plattformübergreifende Unterstützung
Hilfe erhalten
Für Ältere SOAP-Clientprobleme:
- Azure DevOps Developer Community überprüfen
- Überprüfen des Migrationsleitfadens für moderne Alternativen
- Berücksichtigen sie professionelle Migrationsdienste für große Anwendungen
Verwandte Ressourcen
Migrationsressourcen:
- Beispiele für moderne .NET-Clientbibliotheken – Empfohlene Ersetzung
- Authentifizierungsleitfaden – Moderne Authentifizierungsoptionen
- Referenz zur Azure DevOps-REST-API – Vollständige API-Dokumentation
Legacy-Dokumentation:
Von Bedeutung
Planen sie die Migration? Beginnen Sie mit modernen .NET-Clientbibliotheksbeispielen , um die aktuellen bewährten Methoden und Authentifizierungsoptionen anzuzeigen.