Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Azure DevOps Services | Azure DevOps Server | Azure DevOps Server 2022
Ostrzeżenie
Starsza technologia — zalecane nowoczesne alternatywy
Ci klienci oparty na protokole SOAP są starszą technologią i powinni być używane tylko w następujących celach:
- Obsługa istniejących aplikacji, których nie można zmodernizować
- Aplikacje .NET Framework, które wymagają funkcji specyficznych dla protokołu SOAP
W przypadku nowego programowania użyj nowoczesnych bibliotek klienckich platformy .NET opartych na protokole REST, które oferują:
- ✅ Lepsza wydajność i niezawodność
- ✅ Obsługa platform .NET Core, .NET 5+i .NET Framework
- ✅ Nowoczesne metody uwierzytelniania (tożsamości zarządzane, jednostki usługi)
- ✅ Wzorce async/await i nowoczesne funkcje języka C#
- ✅ Aktywne programowanie i obsługa techniczna
Ten artykuł zawiera przykłady integracji z usługami Azure DevOps Server i Azure DevOps Services przy użyciu starszych klientów protokołu SOAP. Ci klienci są dostępni tylko w wersji programu .NET Framework i wymagają lokalnych lub starszych metod uwierzytelniania.
Wymagania wstępne i ograniczenia
Wymagania:
- .NET Framework 4.6.1 lub nowszy
- Starsze pakiety NuGet
- Środowisko systemu Windows do obsługi klienta protokołu SOAP
Ograniczenia:
- ❌ Brak obsługi platformy .NET Core lub .NET 5+
- ❌ Ograniczone nowoczesne opcje uwierzytelniania
- ❌ Brak wzorców async/await
- ❌ Zmniejszona wydajność w porównaniu z klientami REST
- ❌ Ograniczona pomoc techniczna i aktualizacje w przyszłości
Wymagane pakiety NuGet:
- Microsoft.TeamFoundationServer.ExtendedClient — starsi klienci PROTOKOŁU SOAP
- Microsoft.TeamFoundationServer.Client — podstawowe interfejsy API usługi Azure DevOps
- Microsoft.VisualStudio.Services.Client — połączenie i uwierzytelnianie
- Microsoft.VisualStudio.Services.InteractiveClient — przepływy uwierzytelniania interakcyjnego
Wskazówki dotyczące migracji
Zalecana ścieżka migracji
Krok 1. Ocena bieżącego użycia
- Identyfikowanie funkcji specyficznych dla protokołu SOAP używanych przez aplikację
- Określanie, czy są dostępne równoważne interfejsy API REST
- Ocena wymagań dotyczących uwierzytelniania
Krok 2. Planowanie strategii migracji
- Natychmiastowe: aktualizowanie uwierzytelniania w celu używania numerów PAT lub identyfikatora Entra firmy Microsoft
- Krótkoterminowa: migrowanie do klientów opartych na protokole REST przy zachowaniu programu .NET Framework
- Długoterminowe: modernizacja platformy .NET Core/.NET 5+ przy użyciu klientów REST
Krok 3. Implementowanie migracji
- Zacznij od aktualizacji uwierzytelniania. Zapoznaj się z poniższymi przykładami.
- Zastąp klientów protokołu SOAP przyrostowo odpowiednikami REST
- Dokładnie przetestuj przed wdrożeniem w środowisku produkcyjnym
Aby uzyskać szczegółowe wskazówki dotyczące migracji, zobacz Przykłady biblioteki klienta platformy .NET.
Przykłady starszych klientów protokołu SOAP
Podstawowe użycie klienta protokołu SOAP
Ważne
W tym przykładzie przedstawiono starsze wzorce tylko do celów referencyjnych. Użyj przykładów opartych na protokole REST na potrzeby nowego programowania.
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;
}
}
}
Starsze metody uwierzytelniania
Ostrzeżenie
Te metody uwierzytelniania mają ograniczenia zabezpieczeń. Migrowanie do nowoczesnego uwierzytelniania , jeśli jest to możliwe.
Uwierzytelnianie osobistego tokenu dostępu (niezalecane)
/// <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;
}
}
Uwierzytelnianie Microsoft Entra (ograniczone wsparcie)
/// <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;
}
}
Uwierzytelnianie interakcyjne (tylko platforma.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;
}
}
Uwierzytelnianie za pomocą nazwy użytkownika/hasła (przestarzałe)
Ostrzeżenie
Uwierzytelnianie nazwy użytkownika/hasła jest przestarzałe i niezabezpieczone. Zamiast tego należy użyć sieci PAT lub nowoczesnych metod uwierzytelniania.
/// <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;
}
}
Kompletny przykład dziedzictwa
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();
}
}
Migracja do nowoczesnych klientów
Porównanie równoległe
Starsze podejście protokołu SOAP:
// ❌ 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
}
Nowoczesne podejście REST:
// ✅ 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
Kluczowe różnice
| Funkcja | Starsza wersja protokołu SOAP | Nowoczesny interfejs REST |
|---|---|---|
| Obsługa platformy | Tylko program .NET Framework | .NET Framework, .NET Core, .NET 5+ |
| Wydajność | Wolniejsze, synchroniczne | Szybsze, asynchroniczne |
| Authentication | Ograniczone opcje | Obsługa pełnego nowoczesnego uwierzytelniania |
| Zasięg interfejsu API | Tylko starsze interfejsy API | Pełne pokrycie interfejsu API REST |
| Pomoc techniczna w przyszłości | Tylko konserwacja | Aktywne programowanie |
| Wzorce kodu | Blokowanie synchroniczne | Wzorce async/await |
Rozwiązywanie problemów ze starszymi klientami
Typowe problemy i rozwiązania
Błędy uwierzytelniania:
- Upewnij się, że usługi PAT mają odpowiednie zakresy
- Zweryfikuj format adresu URL organizacji (w tym kolekcję dla środowisk lokalnych)
- Sprawdzanie ustawień zapory i serwera proxy dla punktów końcowych protokołu SOAP
Problemy z wydajnością:
- Klienci protokołu SOAP są z natury wolniejsze niż REST
- Rozważ operacje wsadowe tam, gdzie to możliwe
- Migrowanie do klientów REST w celu uzyskania lepszej wydajności
Zgodność platformy:
- Klienci protokołu SOAP działają tylko na platformie .NET Framework
- Korzystanie z klientów REST na potrzeby obsługi wielu platform
Uzyskiwanie pomocy
W przypadku starszych problemów z klientem PROTOKOŁU SOAP:
- Sprawdź społeczność deweloperów usługi Azure DevOps
- Zapoznaj się ze wskazówkami dotyczącymi migracji dla nowoczesnych alternatyw
- Rozważ profesjonalne usługi migracji dla dużych aplikacji
Powiązane zasoby
Zasoby migracji:
- Przykłady nowoczesnej biblioteki klienta platformy .NET — zalecane zastąpienie
- Wskazówki dotyczące uwierzytelniania — nowoczesne opcje uwierzytelniania
- Dokumentacja interfejsu API REST usługi Azure DevOps — pełna dokumentacja referencyjna dotycząca interfejsu API
Starsza dokumentacja:
- Pojęcia dotyczące bibliotek klienckich platformy .NET
- Przykłady uwierzytelniania usługi Azure DevOps
Ważne
Planowanie migracji? Zacznij od nowoczesnych przykładów biblioteki klienta platformy .NET , aby zapoznać się z bieżącymi najlepszymi rozwiązaniami i opcjami uwierzytelniania.