Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Azure DevOps Services | Azure DevOps Server | Azure DevOps Server 2022
.NET istemci kitaplıklarını modern kimlik doğrulama yöntemleri ve güvenli kodlama uygulamalarıyla kullanarak Azure DevOps genişletmeyi ve tümleştirmeyi öğrenin.
Tip
Bu makalenin devamında AI kullanarak bu göreve yardımcı olabilirsiniz veya başlamak için Azure DevOps MCP Server ile yapay zeka yardımı sağlama konusuna bakın.
Önkoşullar
Gerekli NuGet paketleri:
- Microsoft.TeamFoundationServer.Client - Temel Azure DevOps API'leri
- Microsoft.VisualStudio.Services.Client - Bağlantı ve kimlik doğrulaması
- Microsoft.VisualStudio.Services.InteractiveClient - Etkileşimli kimlik doğrulama akışları
Kimlik doğrulama önerileri:
- Azure barındırılan uygulamalar: yönetilen kimlikleri kullanın
- CI/CD işlem hatları: Hizmet sorumlularını kullanma
Etkileşimli uygulamalar :Microsoft Entra kimlik doğrulamasını kullanın- Yalnızca eski senaryolar: Kişisel erişim belirteçlerini kullanma
Önemli
Bu makalede, farklı senaryolar için birden çok kimlik doğrulama yöntemi gösterilmektedir. Dağıtım ortamınıza ve güvenlik gereksinimlerinize göre en uygun yöntemi seçin.
Çekirdek bağlantı ve iş öğesi örneği
Bu kapsamlı örnek, Azure DevOps bağlanmaya ve iş öğeleriyle çalışmaya yönelik en iyi yöntemleri gösterir:
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
using Microsoft.VisualStudio.Services.Client;
using Microsoft.VisualStudio.Services.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
/// <summary>
/// Demonstrates secure Azure DevOps integration with proper error handling and resource management
/// </summary>
public class AzureDevOpsService
{
private readonly VssConnection _connection;
private readonly WorkItemTrackingHttpClient _witClient;
public AzureDevOpsService(string organizationUrl, VssCredentials credentials)
{
// Create connection with proper credential management
_connection = new VssConnection(new Uri(organizationUrl), credentials);
// Get work item tracking client (reused for efficiency)
_witClient = _connection.GetClient<WorkItemTrackingHttpClient>();
}
/// <summary>
/// Creates a work item query, executes it, and returns results with proper error handling
/// </summary>
public async Task<IEnumerable<WorkItem>> GetNewBugsAsync(string projectName)
{
try
{
// Get query hierarchy with proper depth control
var queryHierarchyItems = await _witClient.GetQueriesAsync(projectName, depth: 2);
// Find 'My Queries' folder using safe navigation
var myQueriesFolder = queryHierarchyItems
.FirstOrDefault(qhi => qhi.Name.Equals("My Queries", StringComparison.OrdinalIgnoreCase));
if (myQueriesFolder == null)
{
throw new InvalidOperationException("'My Queries' folder not found in project.");
}
const string queryName = "New Bugs Query";
// Check if query already exists
var existingQuery = myQueriesFolder.Children?
.FirstOrDefault(qhi => qhi.Name.Equals(queryName, StringComparison.OrdinalIgnoreCase));
QueryHierarchyItem query;
if (existingQuery == null)
{
// Create new query with proper WIQL
query = new QueryHierarchyItem
{
Name = queryName,
Wiql = @"
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",
IsFolder = false
};
query = await _witClient.CreateQueryAsync(query, projectName, myQueriesFolder.Name);
}
else
{
query = existingQuery;
}
// Execute query and get results
var queryResult = await _witClient.QueryByIdAsync(query.Id);
if (!queryResult.WorkItems.Any())
{
return Enumerable.Empty<WorkItem>();
}
// Batch process work items for efficiency
const int batchSize = 100;
var allWorkItems = new List<WorkItem>();
for (int skip = 0; skip < queryResult.WorkItems.Count(); skip += batchSize)
{
var batch = queryResult.WorkItems.Skip(skip).Take(batchSize);
var workItemIds = batch.Select(wir => wir.Id).ToArray();
// Get detailed work item information
var workItems = await _witClient.GetWorkItemsAsync(
ids: workItemIds,
fields: new[] { "System.Id", "System.Title", "System.State",
"System.AssignedTo", "System.CreatedDate" });
allWorkItems.AddRange(workItems);
}
return allWorkItems;
}
catch (Exception ex)
{
// Log error appropriately in real applications
throw new InvalidOperationException($"Failed to retrieve work items: {ex.Message}", ex);
}
}
/// <summary>
/// Properly dispose of resources
/// </summary>
public void Dispose()
{
_witClient?.Dispose();
_connection?.Dispose();
}
}
Kimlik doğrulama yöntemleri
Microsoft Entra kimlik doğrulaması (Önerilen)
Etkileşimli kimlik doğrulamasını destekleyen veya Microsoft Entra belirteçleri olan uygulamalar için:
using Microsoft.VisualStudio.Services.Client;
using Microsoft.VisualStudio.Services.Common;
/// <summary>
/// Authenticate using Microsoft Entra ID credentials
/// Recommended for interactive applications and modern authentication scenarios
/// </summary>
public static VssConnection CreateEntraConnection(string organizationUrl, string accessToken)
{
// Use Microsoft Entra access token for authentication
var credentials = new VssOAuthAccessTokenCredential(accessToken);
return new VssConnection(new Uri(organizationUrl), credentials);
}
/// <summary>
/// For device code flow (cross-platform interactive authentication)
/// Works with .NET Core, .NET 5+, and .NET Framework
/// </summary>
public static async Task<VssConnection> CreateEntraDeviceCodeConnectionAsync(
string organizationUrl, string clientId, string tenantId)
{
var app = PublicClientApplicationBuilder
.Create(clientId)
.WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}"))
.Build();
var result = await app
.AcquireTokenWithDeviceCode(
new[] { "https://app.vssps.visualstudio.com/.default" },
callback =>
{
Console.WriteLine(callback.Message);
return Task.CompletedTask;
})
.ExecuteAsync();
var credentials = new VssOAuthAccessTokenCredential(result.AccessToken);
return new VssConnection(new Uri(organizationUrl), credentials);
}
Hizmet sorumlusu kimlik doğrulaması
Otomatik senaryolar ve CI/CD işlem hatları için:
using Microsoft.Identity.Client;
using Microsoft.VisualStudio.Services.Client;
/// <summary>
/// Authenticate using service principal with certificate (most secure)
/// Recommended for production automation scenarios
/// </summary>
public static async Task<VssConnection> CreateServicePrincipalConnectionAsync(
string organizationUrl,
string clientId,
string tenantId,
X509Certificate2 certificate)
{
try
{
// Create confidential client application with certificate
var app = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithCertificate(certificate)
.WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}"))
.Build();
// Acquire token for Azure DevOps
var result = await app
.AcquireTokenForClient(new[] { "https://app.vssps.visualstudio.com/.default" })
.ExecuteAsync();
// Create connection with acquired token
var credentials = new VssOAuthAccessTokenCredential(result.AccessToken);
return new VssConnection(new Uri(organizationUrl), credentials);
}
catch (Exception ex)
{
throw new AuthenticationException($"Failed to authenticate service principal: {ex.Message}", ex);
}
}
/// <summary>
/// Service principal with client secret (less secure than certificate)
/// </summary>
public static async Task<VssConnection> CreateServicePrincipalSecretConnectionAsync(
string organizationUrl,
string clientId,
string tenantId,
string clientSecret)
{
var app = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithClientSecret(clientSecret)
.WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}"))
.Build();
var result = await app
.AcquireTokenForClient(new[] { "https://app.vssps.visualstudio.com/.default" })
.ExecuteAsync();
var credentials = new VssOAuthAccessTokenCredential(result.AccessToken);
return new VssConnection(new Uri(organizationUrl), credentials);
}
Yönetilen kimlik doğrulaması
Azure barındırılan uygulamalar için (bulut senaryoları için önerilir):
using Azure.Identity;
using Azure.Core;
using Microsoft.VisualStudio.Services.Client;
/// <summary>
/// Authenticate using managed identity (most secure for Azure-hosted apps)
/// No credentials to manage - Azure handles everything automatically
/// </summary>
public static async Task<VssConnection> CreateManagedIdentityConnectionAsync(string organizationUrl)
{
try
{
// Use system-assigned managed identity
var credential = new ManagedIdentityCredential();
// Acquire token for Azure DevOps
var tokenRequest = new TokenRequestContext(new[] { "https://app.vssps.visualstudio.com/.default" });
var tokenResponse = await credential.GetTokenAsync(tokenRequest);
// Create connection with managed identity token
var credentials = new VssOAuthAccessTokenCredential(tokenResponse.Token);
return new VssConnection(new Uri(organizationUrl), credentials);
}
catch (Exception ex)
{
throw new AuthenticationException($"Failed to authenticate with managed identity: {ex.Message}", ex);
}
}
/// <summary>
/// Use user-assigned managed identity with specific client ID
/// </summary>
public static async Task<VssConnection> CreateUserAssignedManagedIdentityConnectionAsync(
string organizationUrl,
string managedIdentityClientId)
{
var credential = new ManagedIdentityCredential(managedIdentityClientId);
var tokenRequest = new TokenRequestContext(new[] { "https://app.vssps.visualstudio.com/.default" });
var tokenResponse = await credential.GetTokenAsync(tokenRequest);
var credentials = new VssOAuthAccessTokenCredential(tokenResponse.Token);
return new VssConnection(new Uri(organizationUrl), credentials);
}
Etkileşimli kimlik doğrulaması
Kullanıcının oturum açmasını gerektiren masaüstü uygulamaları için:
.NET Framework
/// <summary>
/// Interactive authentication with Visual Studio sign-in prompt
/// .NET Framework only - not supported in .NET Core/.NET 5+
/// </summary>
public static VssConnection CreateInteractiveConnection(string organizationUrl)
{
var credentials = new VssClientCredentials();
return new VssConnection(new Uri(organizationUrl), credentials);
}
.NET Core / .NET 5+
Platformlar arası etkileşimli kimlik doğrulaması için MSAL cihaz kodunu veya sistem tarayıcı akışını kullanın.
CreateEntraDeviceCodeConnectionAsync içindeki örneğine bakın veya sistem tarayıcısı yaklaşımını kullanın:
var app = PublicClientApplicationBuilder
.Create(clientId)
.WithRedirectUri("http://localhost")
.WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}"))
.Build();
var result = await app
.AcquireTokenInteractive(new[] { "https://app.vssps.visualstudio.com/.default" })
.ExecuteAsync();
var credentials = new VssOAuthAccessTokenCredential(result.AccessToken);
var connection = new VssConnection(new Uri(organizationUrl), credentials);
Kişisel erişim belirteci kimlik doğrulaması (Eski)
Önemli
Daha yüksek riskli personal erişim belirteçleri üzerinde daha güvenli Microsoft Entra belirteçleri kullanmayı göz önünde bulundurun. Daha fazla bilgi için bkz . PAT kullanımını azaltma. İhtiyaçlarınıza uygun kimlik doğrulama mekanizmasını seçmek için kimlik doğrulama kılavuzunu gözden geçirin.
PAT kullanmanız gerekiyorsa, bir tane oluşturmak için kişisel erişim belirteçleri oluşturma bölümüne bakın. Ardından VssBasicCredential olarak geçirin.
var credentials = new VssBasicCredential(string.Empty, personalAccessToken);
var connection = new VssConnection(new Uri(organizationUrl), credentials);
Tam kullanım örnekleri
yönetilen kimlikle Azure İşlevi
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
public class AzureDevOpsFunction
{
private readonly ILogger<AzureDevOpsFunction> _logger;
public AzureDevOpsFunction(ILogger<AzureDevOpsFunction> logger)
{
_logger = logger;
}
[Function("ProcessWorkItems")]
public async Task<string> ProcessWorkItems(
[TimerTrigger("0 0 8 * * MON")] TimerInfo timer)
{
try
{
var organizationUrl = Environment.GetEnvironmentVariable("AZURE_DEVOPS_ORG_URL");
var projectName = Environment.GetEnvironmentVariable("AZURE_DEVOPS_PROJECT");
// Use managed identity for secure authentication
using var connection = await CreateManagedIdentityConnectionAsync(organizationUrl);
using var service = new AzureDevOpsService(organizationUrl, connection.Credentials);
var workItems = await service.GetNewBugsAsync(projectName);
_logger.LogInformation($"Processed {workItems.Count()} work items");
return $"Successfully processed {workItems.Count()} work items";
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to process work items");
throw;
}
}
}
Hizmet sorumlusu ile konsol uygulaması
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
class Program
{
static async Task Main(string[] args)
{
// Configure logging and configuration
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables()
.Build();
using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
var logger = loggerFactory.CreateLogger<Program>();
try
{
var settings = configuration.GetSection("AzureDevOps");
var organizationUrl = settings["OrganizationUrl"];
var projectName = settings["ProjectName"];
var clientId = settings["ClientId"];
var tenantId = settings["TenantId"];
var clientSecret = settings["ClientSecret"]; // Better: use Key Vault
// Authenticate with service principal
using var connection = await CreateServicePrincipalSecretConnectionAsync(
organizationUrl, clientId, tenantId, clientSecret);
using var service = new AzureDevOpsService(organizationUrl, connection.Credentials);
// Process work items
var workItems = await service.GetNewBugsAsync(projectName);
foreach (var workItem in workItems)
{
Console.WriteLine($"Bug {workItem.Id}: {workItem.Fields["System.Title"]}");
}
logger.LogInformation($"Successfully processed {workItems.Count()} work items");
}
catch (Exception ex)
{
logger.LogError(ex, "Application failed");
Environment.Exit(1);
}
}
}
En iyi yöntemler
Güvenlikle ilgili dikkat edilmesi gerekenler
Kimlik bilgisi yönetimi:
- Kaynak kodunda kimlik bilgilerini asla sabit kodlama
- Gizli bilgileri depolamak için Azure Key Vault kullanın
- Azure barındırılan uygulamalar için yönetilen kimlikleri tercih edin
- İstemci gizli bilgileri yerine sertifikaları tercih edin ile hizmet ilkeleri için
- Güvenlik ilkelerini izleyerek kimlik bilgilerini düzenli olarak döndürme
Erişim denetimi:
- En düşük ayrıcalık ilkesini uygulama
- Belgeleri alırken belirli kapsamları kullanın
- Kimlik doğrulama olaylarını izleme ve denetleme
- Uygun durumlarda koşullu erişim ilkeleri uygulama
Performans iyileştirme
Bağlantı yönetimi:
- VssConnection örneklerini işlemler arasında yeniden kullanma
- Bağlantı nesnesi aracılığıyla HTTP istemcilerini havuza alma
- Uygun elden çıkarma yöntemlerini uygulama
- Zaman aşımlarını uygun şekilde yapılandırma
Toplu işlemler:
- İş öğelerini toplu olarak işleme (önerilen: 100 öğe)
- Bağımsız işlemler için paralel işleme kullanma
- Üstel geri alma ile yeniden deneme mantığını uygulama
- Uygun olduğunda sık erişilen verileri önbelleğe alma
Hata yönetimi
public async Task<T> ExecuteWithRetryAsync<T>(Func<Task<T>> operation, int maxRetries = 3)
{
var retryCount = 0;
var baseDelay = TimeSpan.FromSeconds(1);
while (retryCount < maxRetries)
{
try
{
return await operation();
}
catch (Exception ex) when (IsTransientError(ex) && retryCount < maxRetries - 1)
{
retryCount++;
var delay = TimeSpan.FromMilliseconds(baseDelay.TotalMilliseconds * Math.Pow(2, retryCount));
await Task.Delay(delay);
}
}
// Final attempt without catch
return await operation();
}
private static bool IsTransientError(Exception ex)
{
return ex is HttpRequestException ||
ex is TaskCanceledException ||
(ex is VssServiceException vssEx && vssEx.HttpStatusCode >= 500);
}
Geçiş kılavuzu
PAT'lerden modern kimlik doğrulamasına
1. Adım: Mevcut kullanımı değerlendirme
- PAT'leri kullanarak tüm uygulamaları tanımlama
- Dağıtım ortamlarını belirleme (Azure ve şirket içi)
- Güvenlik gereksinimlerini değerlendirme
2. Adım: Değiştirme yöntemini seçme
- Azure üzerinde barındırılan: Yönetilen kimliklere geçiş
- CI/CD boru hatları: Hizmet ilkelerini kullanma
- Interactive apps: Microsoft Entra kimlik doğrulamayı uygulama
- Masaüstü uygulamaları: Cihaz kodu akışını göz önünde bulundurun
3. Adım: Uygulama
- Önceki örnekleri kullanarak kimlik doğrulama kodunu güncelleştirme
- Geliştirme ortamında kapsamlı bir şekilde test edin
- Üretime kademeli olarak dağıtma
- Kimlik doğrulama sorunlarını izleme
Ayrıntılı geçiş kılavuzu için bkz. SP'leri Microsoft Entra belirteçleriyle değiştirme.
.NET istemci kodu oluşturmak için yapay zeka kullanma
Aracı modunda yapay zeka aracınıza bağlı Azure DevOps MCP Server varsa, Azure DevOps için .NET istemci kitaplığı kodu oluşturmak için doğal dil istemlerini kullanabilirsiniz.
| Görev | Örnek talimat |
|---|---|
| İş öğesi sorgusu oluşturma | Write C# code using the Azure DevOps .NET client library to create a work item query, execute it, and process the results |
| Git depolarını ve taahhütleri listele | Show me how to use the Azure DevOps GitHttpClient to list repositories and get recent commits in a project |
| Yönetilen kimlikle bağlanma | Create a .NET application that connects to Azure DevOps using managed identity and retrieves build definitions |
| Etkileşimli Entra oturum açma | Write code to authenticate to Azure DevOps using the .NET client library with interactive Microsoft Entra sign-in |
| Ekip ayarlarını yönetme | Write C# code using the Azure DevOps .NET client to get team members and iteration paths for a project |
| İşlem hattı çalıştırmasını başlatın | Show me how to trigger a pipeline run in Azure DevOps using the .NET client libraries with service principal authentication |
Uyarı
Aracı modu ve MCP Sunucusu doğal dil kullandığından, bu istemleri ayarlayabilir veya sonuçları iyileştirmek için takip soruları sorabilirsiniz.
İlgili kaynaklar
- Azure DevOps için Kimlik Doğrulama Kılavuzu
- Hizmet sorumluları ve yönetilen kimlikler
- Microsoft Entra kimlik doğrulaması
- .NET istemci kitaplıkları kavramları
- Azure DevOps kimlik doğrulama örnekleri
- Microsoft kimlik platformu belgeleri