Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Azure DevOps Services | Azure DevOps Server | Azure DevOps Server 2022
Предупреждение
Устаревшая технология — современные альтернативные варианты, рекомендуемые
Эти клиенты на основе SOAP являются устаревшими технологиями и должны использоваться только для:
- Обслуживание существующих приложений, которые нельзя модернизировать
- Приложения .NET Framework, требующие функциональных возможностей, относящихся к SOAP
Для новой разработки используйте современные клиентские библиотеки .NET на основе REST , которые предлагают:
- ✅ Повышение производительности и надежности
- ✅ Поддержка .NET Core, .NET 5+ и .NET Framework
- ✅ Современные методы аутентификации (управляемые удостоверения, служебные главные компоненты)
- ✅ Асинхронные и ожидаемые шаблоны и современные возможности C#
- ✅ Активная разработка и поддержка
В этой статье содержатся примеры интеграции с Azure DevOps Server и Azure DevOps Services с использованием устаревших клиентов SOAP. Эти клиенты доступны только в версии .NET Framework и требуют локальных или устаревших методов проверки подлинности.
Предварительные требования и ограничения
Требования:
- .NET Framework 4.6.1 или более поздней версии
- Устаревшие пакеты NuGet
- Среда Windows для поддержки клиентов SOAP
Ограничения:
- ❌ Нет поддержки .NET Core или .NET 5+
- ❌ Ограниченные современные параметры проверки подлинности
- ❌ Нет асинхронных и ожидаемых шаблонов
- ❌ Снижение производительности по сравнению с клиентами REST
- ❌ Ограниченная будущая поддержка и обновления
Обязательные пакеты NuGet:
- Microsoft.TeamFoundationServer.ExtendedClient — устаревшие клиенты SOAP
- Microsoft.TeamFoundationServer.Client — основные API Azure DevOps
- Microsoft.VisualStudio.Services.Client — подключение и проверка подлинности
- Microsoft.VisualStudio.Services.InteractiveClient — интерактивные потоки проверки подлинности
Руководство по миграции
Рекомендуемый путь миграции
Шаг 1. Оценка текущего использования
- Определение функциональных возможностей, относящихся к SOAP, которые использует приложение
- Определите, доступны ли эквивалентные REST API
- Оценка требований к проверке подлинности
Шаг 2. Планирование стратегии миграции
- Немедленно. Обновление проверки подлинности для использования идентификатора Microsoft Entra
- Кратковременная миграция на клиенты на основе REST при сохранении платформы .NET Framework
- Долгосрочное: модернизация до .NET Core/.NET 5+ с помощью клиентов REST
Шаг 3. Реализация миграции
- Начните с обновлений аутентификации. Ознакомьтесь с приведенными ниже примерами.
- Постепенно замените клиенты SOAP эквивалентами REST
- Тщательно протестируйте перед развертыванием в рабочей среде
Подробные рекомендации по миграции см. в примерах клиентской библиотеки .NET.
Устаревшие примеры клиента SOAP
Базовое использование клиента SOAP
Это важно
В этом примере показаны устаревшие шаблоны только для ссылок. Используйте примеры на основе REST для новой разработки.
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;
}
}
}
Устаревшие методы проверки подлинности
Предупреждение
Эти методы проверки подлинности имеют ограничения безопасности. Перейдите на современную проверку подлинности при возможности.
Аутентификация с помощью токена личного доступа (не рекомендуется)
Это важно
Рассмотрите возможность использования более безопасных маркеров Microsoft Entra по сравнению с более высоким уровнем риска персональных маркеров доступа. Дополнительные сведения см. в разделе "Сокращение использования PAT". Просмотрите рекомендации по проверке подлинности , чтобы выбрать правильный механизм проверки подлинности для ваших потребностей.
Если необходимо использовать PAT, см. раздел «Использование личных маркеров доступа» для их создания.
Затем передайте его в виде VssBasicCredential:
var credentials = new VssBasicCredential(string.Empty, personalAccessToken);
using (var tpc = new TfsTeamProjectCollection(new Uri(collectionUri), credentials))
{
tpc.Authenticate();
}
Проверка подлинности Microsoft Entra (ограниченная поддержка)
/// <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;
}
}
Интерактивная проверка подлинности (только для .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;
}
}
Проверка подлинности имени пользователя и пароля (не рекомендуется)
Осторожность
Проверка подлинности имени пользователя и пароля устарела и небезопасна. Вместо этого используйте современные методы проверки подлинности.
/// <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 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. Migrate to modern authentication.");
throw;
}
}
Полный пример устаревшей системы
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))
{
// Use PAT authentication (consider migrating to modern auth)
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();
}
}
Миграция на современные клиентские приложения
Параллельное сравнение
Устаревший подход 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
}
Современный подход 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
Основные отличия
| Функция | Устаревшая версия SOAP | Современный REST |
|---|---|---|
| Поддержка платформы | Только .NET Framework | .NET Framework, .NET Core, .NET 5+ |
| Производительность | Медленнее, синхронно | Быстрее, асинхронно |
| Аутентификация | Ограниченные параметры | Полная современная поддержка проверки подлинности |
| Покрытие API | Только устаревшие API | Полный охват REST API |
| Будущая поддержка | Только обслуживание | Активная разработка |
| Шаблоны кода | Синхронная блокировка | Асинхронные и ожидаемые шаблоны |
Устранение неполадок устаревших клиентов
Распространенные проблемы и решения
Сбои проверки подлинности:
- Убедитесь, что PATs имеют соответствующие области
- Проверить формат URL организации (добавить коллекцию для локальной среды)
- Проверка параметров брандмауэра и прокси-сервера для конечных точек SOAP
Проблемы с производительностью:
- Клиенты SOAP по сути медленнее, чем REST
- Рассмотрите возможность пакетных операций, когда это возможно
- Миграция на клиенты REST для повышения производительности
Совместимость платформы:
- Клиенты SOAP работают только в .NET Framework
- Использование клиентов REST для кроссплатформенной поддержки
Получение помощи
Для устаревших проблем с клиентом SOAP:
- Ознакомьтесь с сообществом разработчиков Azure DevOps
- Ознакомьтесь с рекомендациями по миграции для современных альтернатив
- Рассмотрим профессиональные службы миграции для крупных приложений
Связанные ресурсы
Ресурсы миграции:
- Примеры современной клиентской библиотеки .NET — рекомендуемая замена
- Руководство по проверке подлинности — современные параметры проверки подлинности
- Справочник по REST API Azure DevOps . Полная документация по API
Устаревшая документация:
Это важно
Планирование миграции? Начните с современных примеров клиентской библиотеки .NET , чтобы просмотреть текущие рекомендации и параметры проверки подлинности.