Azure DevOps Services |Azure DevOps Server |Azure DevOps Server 2022
Warnung
レガシ テクノロジ - 推奨される最新の代替手段
これらの SOAP ベースのクライアントはレガシ テクノロジであり、次の場合にのみ使用する必要があります。
- 最新化できない既存のアプリケーションの維持
- SOAP 固有の機能を必要とする .NET Framework アプリケーション
新しい開発では、次を提供する最新 の REST ベースの .NET クライアント ライブラリを 使用します。
- ✅ パフォーマンスと信頼性の向上
- ✅ .NET Core、.NET 5 以降、および .NET Framework のサポート
- ✅ 先進認証方法 (マネージド ID、サービス プリンシパル)
- ✅ 非同期/待機パターンと最新の C# 機能
- ✅ アクティブな開発とサポート
この記事には、レガシ SOAP クライアントを使用して Azure DevOps Server および Azure DevOps Services と統合するためのサンプルが含まれています。 これらのクライアントは .NET Framework バージョンでのみ使用でき、オンプレミスまたはレガシ認証方法が必要です。
前提条件と制限事項
要件:
- .NET Framework 4.6.1 以降
- レガシ NuGet パッケージ
- SOAP クライアントサポート用の Windows 環境
制限:
- ❌ .NET Core または .NET 5 以降のサポートなし
- ❌ 先進認証オプションの制限
- ❌ 非同期/待機パターンなし
- ❌ REST クライアントと比較してパフォーマンスが低下する
- ❌ 今後のサポートと更新プログラムの制限
必要な NuGet パッケージ:
- Microsoft.TeamFoundationServer.ExtendedClient - レガシ SOAP クライアント
- Microsoft.TeamFoundationServer.Client - コア Azure DevOps API
- Microsoft.VisualStudio.Services.Client - 接続と認証
- Microsoft.VisualStudio.Services.InteractiveClient - 対話型認証フロー
移行ガイダンス
推奨される移行パス
手順 1: 現在の使用状況を評価する
- アプリケーションで使用される SOAP 固有の機能を特定する
- 同等の REST API が使用可能かどうかを判断する
- 認証要件を評価する
手順 2: 移行戦略を計画する
- イミディエイト: 認証を更新して、AT または Microsoft Entra ID を使用する
- 短期的: .NET Framework を維持しながら REST ベースのクライアントに移行する
- 長期的: REST クライアントを使用して .NET Core/.NET 5 以降に最新化する
手順 3: 移行を実装する
- 認証の更新から始めます。 次の例を参照してください。
- SOAP クライアントを REST と同等のものに増分的に置き換える
- 運用環境にデプロイする前に十分にテストする
移行の詳細なガイダンスについては、 .NET クライアント ライブラリのサンプルを参照してください。
従来の SOAP クライアントの例
基本的な SOAP クライアントの使用
Von Bedeutung
この例では、参照専用のレガシ パターンを示します。 新しい開発 には 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;
}
}
}
従来の認証方法
Warnung
これらの認証方法には、セキュリティの制限があります。 可能であれば 、先進認証 に移行します。
個人用アクセス トークン認証 (推奨されません)
/// <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 認証 (制限付きサポート)
/// <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;
}
}
ユーザー名/パスワード認証 (非推奨)
注意事項
ユーザー名/パスワード認証は非推奨であり、安全ではありません。 代わりに、PAT または最新の認証方法を使用してください。
/// <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;
}
}
包括的なレガシー例
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();
}
}
最新のクライアントへの移行
並べて比較
従来の 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 カバレッジ |
| 今後のサポート | メンテナンスのみ | アクティブな開発 |
| コード パターン | 同期ブロッキング | 非同期/待機パターン |
レガシ クライアントのトラブルシューティング
一般的な問題と解決策
認証エラー:
- PAT に適切なスコープがあることを確認する
- 組織の URL 形式を確認する (オンプレミスのコレクションを含む)
- SOAP エンドポイントのファイアウォールとプロキシの設定を確認する
パフォーマンスの問題:
- SOAP クライアントは本質的に REST よりも遅い
- 可能な限りバッチ操作を検討する
- パフォーマンスを向上させるために REST クライアントに移行する
プラットフォームの互換性:
- SOAP クライアントは .NET Framework でのみ機能します
- クロスプラットフォーム サポートに REST クライアントを使用する
ヘルプを受ける
従来の SOAP クライアントの問題の場合:
- Azure DevOps 開発者コミュニティを確認する
- 最新の代替手段の 移行ガイダンス を確認する
- 大規模なアプリケーション向けのプロフェッショナルな移行サービスを検討する
関連リソース
移行リソース:
- 最新の .NET クライアント ライブラリのサンプル - 推奨される置換
- 認証ガイダンス - 先進認証オプション
- Azure DevOps REST API リファレンス - 完全な API ドキュメント
レガシードキュメント:
Von Bedeutung
移行を計画していますか? 最新の .NET クライアント ライブラリのサンプル から始めて、現在のベスト プラクティスと認証オプションを確認します。