Delen via


REST API-voorbeelden voor Azure DevOps

Azure DevOps Services | Azure DevOps Server | Azure DevOps Server 2022

Dit artikel bevat praktische REST API-voorbeelden voor Azure DevOps Services. Deze voorbeelden laten algemene bewerkingen zien, zoals het ophalen van projecten, het beheren van werkitems en het gebruik van veilige verificatiepatronen met Microsoft Entra-id.

Belangrijk

Deze voorbeelden maken gebruik van Microsoft Entra ID-verificatie. Dit is de aanbevolen benadering voor productietoepassingen. Hoewel persoonlijke toegangstokens (PAT's) kunnen worden gebruikt voor eenvoudige scripts, biedt Microsoft Entra ID betere beveiligings- en governancemogelijkheden.

Overzicht van verificatie

Azure DevOps REST API's ondersteunen verschillende verificatiemethoden:

  • Microsoft Entra-id - Aanbevolen voor productietoepassingen (gebruikt in deze voorbeelden)
  • Persoonlijke toegangstokens (PAT's) - Eenvoudige verificatie voor scripts en testen
  • OAuth 2.0 - Voor toepassingen van derden
  • Serviceprincipals - voor geautomatiseerde scenario's

Belangrijk

We raden u aan de veiligere Microsoft Entra-tokens te gebruiken voor persoonlijke toegangstokens met een hoger risico. Meer informatie over onze inspanningen om het PAT-gebruik te verminderen. Bekijk onze verificatierichtlijnen om het juiste verificatiemechanisme voor uw behoeften te kiezen.

Microsoft Entra ID-verificatie

Voor Microsoft Entra ID-verificatie moet u een toepassing registreren en een toegangstoken verkrijgen. U kunt als volgt verifiëren met behulp van de Microsoft Authentication Library (MSAL):

Installeer eerst het vereiste NuGet-pakket:

<PackageReference Include="Microsoft.Identity.Client" Version="4.61.3" />
using Microsoft.Identity.Client;
using System.Net.Http.Headers;

public async Task<string> GetAccessTokenAsync()
{
    var app = PublicClientApplicationBuilder
        .Create("{your-client-id}")
        .WithAuthority("https://login.microsoftonline.com/{your-tenant-id}")
        .WithRedirectUri("http://localhost")
        .Build();

    var scopes = new[] { "https://app.vssps.visualstudio.com/.default" };
    
    try
    {
        var result = await app.AcquireTokenInteractive(scopes).ExecuteAsync();
        return result.AccessToken;
    }
    catch (MsalException ex)
    {
        Console.WriteLine($"Authentication failed: {ex.Message}");
        throw;
    }
}

REST API-voorbeelden

Projecten weergeven (GET)

Alle projecten in uw organisatie ophalen:

C#-voorbeeld

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Microsoft.Identity.Client;

public async Task<string> GetProjectsAsync(string organization)
{
    using var client = new HttpClient();
    
    // Get Microsoft Entra ID access token
    var entraIdAccessToken = await GetAccessTokenAsync();
    
    // Set base address and headers
    client.BaseAddress = new Uri($"https://dev.azure.com/{organization}/");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
    // Add authentication header
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", entraIdAccessToken);
    
    try
    {
        var response = await client.GetAsync("_apis/projects?api-version=7.2");
        response.EnsureSuccessStatusCode();
        
        return await response.Content.ReadAsStringAsync();
    }
    catch (HttpRequestException ex)
    {
        Console.WriteLine($"Request failed: {ex.Message}");
        throw;
    }
}

PowerShell-voorbeeld

# Install required module if not already installed
# Install-Module -Name MSAL.PS -Force

Import-Module MSAL.PS

$clientId = "your-client-id"
$tenantId = "your-tenant-id"
$organization = "your-organization"

# Get access token
$token = Get-MsalToken -ClientId $clientId -TenantId $tenantId -Scopes "https://app.vssps.visualstudio.com/.default"

$headers = @{
    'Authorization' = "Bearer $($token.AccessToken)"
    'Accept' = 'application/json'
}

$uri = "https://dev.azure.com/$organization/_apis/projects?api-version=7.2"

try {
    $response = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers
    Write-Host "Retrieved $($response.count) projects"
    $response.value | ForEach-Object { Write-Host "- $($_.name)" }
}
catch {
    Write-Error "Failed to retrieve projects: $($_.Exception.Message)"
}

Werkitem maken (POST)

Maak een nieuw werkitem in uw project:

C#-voorbeeld

using System.Text;
using Newtonsoft.Json;

public async Task<string> CreateWorkItemAsync(string organization, string project)
{
    using var client = new HttpClient();
    
    // Get Microsoft Entra ID access token
    var entraIdAccessToken = await GetAccessTokenAsync();
    
    // Set base address and headers
    client.BaseAddress = new Uri($"https://dev.azure.com/{organization}/");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", entraIdAccessToken);
    
    var workItem = new
    {
        fields = new
        {
            SystemTitle = "Sample work item",
            SystemDescription = "Created via REST API with Microsoft Entra ID",
            SystemTags = "api; sample; entra-id"
        }
    };
    
    var json = JsonConvert.SerializeObject(workItem);
    var content = new StringContent(json, Encoding.UTF8, "application/json");
    
    try
    {
        var response = await client.PostAsync($"{project}/_apis/wit/workitems/$Task?api-version=7.2", content);
        response.EnsureSuccessStatusCode();
        
        return await response.Content.ReadAsStringAsync();
    }
    catch (HttpRequestException ex)
    {
        Console.WriteLine($"Request failed: {ex.Message}");
        throw;
    }
}

PowerShell-voorbeeld

Import-Module MSAL.PS

$clientId = "your-client-id"
$tenantId = "your-tenant-id"
$organization = "your-organization"
$project = "your-project"

# Get access token
$token = Get-MsalToken -ClientId $clientId -TenantId $tenantId -Scopes "https://app.vssps.visualstudio.com/.default"

$headers = @{
    'Authorization' = "Bearer $($token.AccessToken)"
    'Content-Type' = 'application/json'
}

$body = @{
    fields = @{
        'System.Title' = 'Sample work item'
        'System.Description' = 'Created via REST API with Microsoft Entra ID'
        'System.Tags' = 'api; sample; entra-id'
    }
} | ConvertTo-Json

$uri = "https://dev.azure.com/$organization/$project/_apis/wit/workitems/`$Task?api-version=7.2"

try {
    $response = Invoke-RestMethod -Uri $uri -Method Post -Headers $headers -Body $body
    Write-Host "Work item created with ID: $($response.id)"
}
catch {
    Write-Error "Failed to create work item: $($_.Exception.Message)"
}

Werkitem bijwerken (PATCH)

Werk de status van een bestaand werkitem bij:

C#-voorbeeld

using System.Text;
using Newtonsoft.Json;

public async Task<string> UpdateWorkItemAsync(string organization, string project, int workItemId)
{
    using var client = new HttpClient();
    
    // Get Microsoft Entra ID access token
    var entraIdAccessToken = await GetAccessTokenAsync();
    
    // Set base address and headers
    client.BaseAddress = new Uri($"https://dev.azure.com/{organization}/");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", entraIdAccessToken);
    
    var patchOperations = new[]
    {
        new
        {
            op = "add",
            path = "/fields/System.State",
            value = "In Progress"
        },
        new
        {
            op = "add",
            path = "/fields/System.AssignedTo",
            value = "user@example.com"
        }
    };
    
    var json = JsonConvert.SerializeObject(patchOperations);
    var content = new StringContent(json, Encoding.UTF8, "application/json-patch+json");
    
    try
    {
        var response = await client.PatchAsync($"{project}/_apis/wit/workitems/{workItemId}?api-version=7.2", content);
        response.EnsureSuccessStatusCode();
        
        return await response.Content.ReadAsStringAsync();
    }
    catch (HttpRequestException ex)
    {
        Console.WriteLine($"Request failed: {ex.Message}");
        throw;
    }
}

PowerShell-voorbeeld

Import-Module MSAL.PS

$clientId = "your-client-id"
$tenantId = "your-tenant-id"
$organization = "your-organization"
$project = "your-project"
$workItemId = 123  # Replace with actual work item ID

# Get access token
$token = Get-MsalToken -ClientId $clientId -TenantId $tenantId -Scopes "https://app.vssps.visualstudio.com/.default"

$headers = @{
    'Authorization' = "Bearer $($token.AccessToken)"
    'Content-Type' = 'application/json-patch+json'
}

$body = @(
    @{
        op = "add"
        path = "/fields/System.State"
        value = "In Progress"
    },
    @{
        op = "add"
        path = "/fields/System.AssignedTo"
        value = "user@example.com"
    }
) | ConvertTo-Json

$uri = "https://dev.azure.com/$organization/$project/_apis/wit/workitems/$workItemId?api-version=7.2"

try {
    $response = Invoke-RestMethod -Uri $uri -Method Patch -Headers $headers -Body $body
    Write-Host "Work item $workItemId updated successfully"
}
catch {
    Write-Error "Failed to update work item: $($_.Exception.Message)"
}

Werkitem verwijderen (DELETE)

Een werkitem uit uw project verwijderen:

C#-voorbeeld

public async Task<bool> DeleteWorkItemAsync(string organization, string project, int workItemId)
{
    using var client = new HttpClient();
    
    // Get Microsoft Entra ID access token
    var entraIdAccessToken = await GetAccessTokenAsync();
    
    // Set base address and headers
    client.BaseAddress = new Uri($"https://dev.azure.com/{organization}/");
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", entraIdAccessToken);
    
    try
    {
        var response = await client.DeleteAsync($"{project}/_apis/wit/workitems/{workItemId}?api-version=7.2");
        response.EnsureSuccessStatusCode();
        
        Console.WriteLine($"Work item {workItemId} deleted successfully");
        return true;
    }
    catch (HttpRequestException ex)
    {
        Console.WriteLine($"Request failed: {ex.Message}");
        throw;
    }
}

.NET-clientbibliotheken

Gebruik voor .NET-toepassingen de Azure DevOps .NET-clientbibliotheken voor betere typeveiligheid en eenvoudigere ontwikkeling.

Installatie

Voeg deze NuGet-pakketten toe aan uw project:

<PackageReference Include="Microsoft.TeamFoundationServer.Client" Version="19.225.1" />
<PackageReference Include="Microsoft.VisualStudio.Services.Client" Version="19.225.1" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.61.3" />

Projecten ophalen met behulp van .NET-client

using Microsoft.TeamFoundation.Core.WebApi;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.WebApi;
using Microsoft.Identity.Client;

public async Task<IEnumerable<TeamProjectReference>> GetProjectsAsync(string organizationUrl)
{
    var uri = new Uri(organizationUrl);
    
    // Get Microsoft Entra ID access token
    var entraIdAccessToken = await GetAccessTokenAsync();
    var credentials = new VssOAuthAccessTokenCredential(entraIdAccessToken);
    
    using var connection = new VssConnection(uri, credentials);
    using var projectClient = connection.GetClient<ProjectHttpClient>();
    
    try
    {
        var projects = await projectClient.GetProjects();
        return projects;
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error retrieving projects: {ex.Message}");
        throw;
    }
}

Werkitem maken met behulp van .NET-client

using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
using Microsoft.VisualStudio.Services.WebApi.Patch;
using Microsoft.VisualStudio.Services.WebApi.Patch.Json;
using Microsoft.Identity.Client;

public async Task<WorkItem> CreateWorkItemAsync(string organizationUrl, string project)
{
    var uri = new Uri(organizationUrl);
    
    // Get Microsoft Entra ID access token
    var entraIdAccessToken = await GetAccessTokenAsync();
    var credentials = new VssOAuthAccessTokenCredential(entraIdAccessToken);
    
    using var connection = new VssConnection(uri, credentials);
    using var witClient = connection.GetClient<WorkItemTrackingHttpClient>();
    
    var patchDocument = new JsonPatchDocument
    {
        new JsonPatchOperation
        {
            Operation = Operation.Add,
            Path = "/fields/System.Title",
            Value = "Sample work item created via .NET client with Microsoft Entra ID"
        },
        new JsonPatchOperation
        {
            Operation = Operation.Add,
            Path = "/fields/System.Description", 
            Value = "This work item was created using the Azure DevOps .NET client library with Microsoft Entra ID authentication"
        }
    };
    
    try
    {
        var workItem = await witClient.CreateWorkItemAsync(patchDocument, project, "Task");
        return workItem;
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error creating work item: {ex.Message}");
        throw;
    }
}

Foutafhandeling

Implementeer altijd de juiste foutafhandeling in uw toepassingen:

try
{
    var response = await client.GetAsync(requestUri);
    response.EnsureSuccessStatusCode();
    var content = await response.Content.ReadAsStringAsync();
    // Process successful response
}
catch (HttpRequestException ex)
{
    // Handle HTTP-related errors
    Console.WriteLine($"HTTP Error: {ex.Message}");
}
catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException)
{
    // Handle timeout
    Console.WriteLine("Request timed out");
}
catch (Exception ex)
{
    // Handle other errors
    Console.WriteLine($"Unexpected error: {ex.Message}");
}

Beste praktijken

  • Microsoft Entra-id gebruiken: Verificatie van Microsoft Entra-id via PAT's gebruiken voor productietoepassingen
  • HTTPS gebruiken: veilige verbindingen altijd gebruiken voor API-aanroepen
  • Ratelimieten beheren: logica implementeren voor opnieuw proberen met exponentiële terugval
  • Cachereacties: sla veelgebruikte gegevens op om API-aanroepen te verminderen
  • Specifieke API-versies gebruiken: vastleggen op specifieke versies om brekende veranderingen te voorkomen
  • Invoer valideren: Gebruikersinvoer altijd valideren voordat API-aanroepen worden uitgevoerd
  • Log op de juiste manier: API-interacties loggen voor foutopsporing, maar nooit credentials registreren
  • Tokenbeheer: de juiste cache- en vernieuwingslogica voor Microsoft Entra-id-tokens implementeren