Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Azure DevOps Services | Azure DevOps Server | Azure DevOps Server 2022
En este artículo se proporcionan ejemplos prácticos de api REST para Azure DevOps Services. En estos ejemplos se muestran operaciones comunes como recuperar proyectos, administrar elementos de trabajo y usar patrones de autenticación seguros con el identificador de Microsoft Entra.
Importante
Estos ejemplos usan la autenticación de Id. de Entra de Microsoft, que es el enfoque recomendado para las aplicaciones de producción. Aunque los tokens de acceso personal (PAT) se pueden usar para scripts simples, Microsoft Entra ID proporciona mejores funcionalidades de seguridad y gobernanza.
Información general sobre la autenticación
Las API REST de Azure DevOps admiten varios métodos de autenticación:
- Id. de Microsoft Entra : recomendado para aplicaciones de producción (usadas en estos ejemplos)
- Tokens de acceso personal (PAT): autenticación sencilla para scripts y pruebas
- OAuth 2.0 : para aplicaciones de terceros
- Entidades de servicio: para escenarios automatizados
Importante
Se recomiendan los tokens de Microsoft Entra más seguros sobre los tokens de acceso personal de mayor riesgo. Obtenga más información sobre nuestros esfuerzos para reducir el uso de PAT. Revise nuestra guía de autenticación para elegir el mecanismo de autenticación adecuado para sus necesidades.
Autenticación de Microsoft Entra ID
Para la autenticación con Microsoft Entra ID, deberá registrar una aplicación y obtener un token de acceso. Aquí se muestra cómo autenticarse mediante la Biblioteca de autenticación de Microsoft (MSAL):
En primer lugar, instale el paquete NuGet necesario:
<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;
}
}
Ejemplos de API REST
Enumerar proyectos (GET)
Recupere todos los proyectos de la organización:
Ejemplo 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;
}
}
Ejemplo de 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)"
}
Crear elemento de trabajo (POST)
Cree un nuevo elemento de trabajo en el proyecto:
Ejemplo 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;
}
}
Ejemplo de 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)"
}
Actualizar elemento de trabajo (PATCH)
Actualice el estado de un elemento de trabajo existente:
Ejemplo 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;
}
}
Ejemplo de 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)"
}
Eliminar elemento de trabajo (DELETE)
Quite un elemento de trabajo del proyecto:
Ejemplo 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 cliente de .NET
En el caso de las aplicaciones .NET, use las bibliotecas cliente de .NET de Azure DevOps para mejorar la seguridad de tipos y facilitar el desarrollo.
Instalación
Agregue estos paquetes NuGet al proyecto:
<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" />
Obtención de proyectos mediante el cliente de .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;
}
}
Creación de un elemento de trabajo mediante el cliente de .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;
}
}
Control de errores
Implemente siempre el control de errores adecuado en las aplicaciones:
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}");
}
procedimientos recomendados
- Utilizar Microsoft Entra ID: Utilice la autenticación de Microsoft Entra ID en lugar de PATs para aplicaciones de producción
- Uso de HTTPS: use siempre conexiones seguras para las llamadas API.
- Controlar los límites de velocidad: implementación de la lógica de reintento con retroceso exponencial
- Respuestas de caché: almacene los datos a los que se accede con frecuencia para reducir las llamadas API.
- Uso de versiones específicas de API: Fijar versiones específicas para evitar cambios disruptivos
- Validar entradas: valide siempre las entradas del usuario antes de realizar llamadas API.
- Registro adecuado: Registrar las interacciones de la API para la depuración, pero nunca registrar credenciales
- Administración de tokens: implementar la lógica adecuada de almacenamiento en caché y actualización para los tokens de Microsoft Entra ID.