Partilhar via


Exemplos de API REST para Azure DevOps

Serviços de DevOps do Azure | Azure DevOps Server | Azure DevOps Server 2022

Este artigo fornece exemplos práticos de API REST para os Serviços de DevOps do Azure. Esses exemplos demonstram operações comuns, como recuperar projetos, gerenciar itens de trabalho e usar padrões de autenticação segura com o Microsoft Entra ID.

Importante

Esses exemplos usam a autenticação Microsoft Entra ID, que é a abordagem recomendada para aplicativos de produção. Enquanto os tokens de acesso pessoal (PATs) podem ser usados para scripts simples, o Microsoft Entra ID oferece melhores recursos de segurança e governança.

Descrição geral da autenticação

As APIs REST do Azure DevOps dão suporte a vários métodos de autenticação:

  • Microsoft Entra ID - Recomendado para aplicativos de produção (usado nestes exemplos)
  • Personal Access Tokens (PATs) - Autenticação simples para scripts e testes
  • OAuth 2.0 - Para aplicações de terceiros
  • Principais de Serviço - Para cenários automatizados

Importante

Recomendamos os tokens Microsoft Entra mais seguros do que os tokens de acesso pessoal de maior risco. Saiba mais sobre os nossos esforços para reduzir a utilização de PAT. Reveja as nossas orientações de autenticação para escolher o mecanismo de autenticação certo para as suas necessidades.

Autenticação do Microsoft Entra ID

Para autenticação do Microsoft Entra ID, você precisará registrar um aplicativo e obter um token de acesso. Veja como autenticar usando a Biblioteca de Autenticação da Microsoft (MSAL):

Primeiro, instale o pacote NuGet necessário:

<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;
    }
}

Exemplos de API REST

Listar projetos (GET)

Recupere todos os projetos em sua organização:

Exemplo de C#

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;
    }
}

Exemplo do PowerShell

# 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)"
}

Criar item de trabalho (POST)

Crie um novo item de trabalho em seu projeto:

Exemplo de C#

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;
    }
}

Exemplo do PowerShell

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)"
}

Atualizar item de trabalho (PATCH)

Atualizar o estado de um item de trabalho existente:

Exemplo de C#

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;
    }
}

Exemplo do PowerShell

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)"
}

Excluir item de trabalho (DELETE)

Remova um item de trabalho do seu projeto:

Exemplo de C#

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;
    }
}

Bibliotecas de cliente .NET

Para aplicativos .NET, use as bibliotecas de cliente .NET do Azure DevOps para melhor segurança de tipo e desenvolvimento mais fácil.

Instalação

Adicione estes pacotes NuGet ao seu projeto:

<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" />

Obter projetos usando o cliente .NET

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;
    }
}

Criar item de trabalho usando o cliente .NET

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;
    }
}

Tratamento de erros

Sempre implemente o tratamento adequado de erros em seus aplicativos:

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}");
}

Melhores práticas

  • Usar o Microsoft Entra ID: Usar a autenticação do Microsoft Entra ID em vez de PATs para aplicações de produção
  • Usar HTTPS: sempre use conexões seguras para chamadas de API
  • Gerir limites de taxa: Implementar lógica de repetição com retorno exponencial
  • Respostas de cache: armazene dados acessados com frequência para reduzir chamadas de API
  • Use versões específicas da API: bloqueie em versões específicas para evitar alterações incompatíveis
  • Validar entradas: sempre valide as entradas do usuário antes de fazer chamadas de API
  • Registrar adequadamente: registrar interações da API para depuração, mas nunca registrar credenciais
  • Gestão de tokens: implementar uma lógica adequada de armazenamento e atualização para tokens do ID do Microsoft Entra