Partager via


Extraire des éléments de travail avec des requêtes par programmation

Azure DevOps Services

L’extraction d’éléments de travail à l’aide de requêtes est un scénario courant dans Azure DevOps Services. Cet article explique comment implémenter ce scénario par programmation à l’aide d’API REST ou de bibliothèques clientes .NET.

Prérequis

Catégorie Spécifications
Azure DevOps - Une organisation.<\br>- Un jeton d’accès personnel (PAT).
environnement de développement Environnement de développement C#. Vous pouvez utiliser Visual Studio.

Importante

Nous utilisons des jetons d’accès personnels (PAT) comme exemple dans cet article, mais nous vous déconseillons d’utiliser des PAT. Pour obtenir des mécanismes d’authentification plus sécurisés, consultez guide d’authentification.

Créer un projet C# dans Visual Studio

Pour plus d’informations sur la programmation C# dans Visual Studio, consultez la documentation de programmation C# de Visual Studio.

Contenu du code C#

Les tâches suivantes se produisent dans l’extrait de code :

  • Authentifier
    1. Créez des informations d’identification à l’aide de votre jeton d’accès personnel (PAT).
    2. Générez le client à l’aide des informations d’identification.
  • Obtenir les éléments de travail
    1. Créez la requête que vous souhaitez utiliser.
    2. Récupérez les résultats de cette requête.
    3. Récupérez chacun des éléments de travail par ID.

Extrait de code C#

// nuget:Microsoft.TeamFoundationServer.Client
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.WebApi;

public class QueryExecutor
{
    private readonly Uri uri;
    private readonly string personalAccessToken;

    /// <summary>
    /// Initializes a new instance of the <see cref="QueryExecutor" /> class.
    /// </summary>
    /// <param name="orgName">
    /// An organization in Azure DevOps Services. If you don't have one, you can create one for free:
    /// <see href="https://go.microsoft.com/fwlink/?LinkId=307137" />.
    /// </param>
    /// <param name="personalAccessToken">
    /// A Personal Access Token, find out how to create one:
    /// <see href="/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops" />.
    /// </param>
    public QueryExecutor(string orgName, string personalAccessToken)
    {
        this.uri = new Uri("https://dev.azure.com/" + orgName);
        this.personalAccessToken = personalAccessToken;
    }

    /// <summary>
    /// Execute a WIQL (Work Item Query Language) query to return a list of open bugs.
    /// </summary>
    /// <param name="project">The name of your project within your organization.</param>
    /// <returns>A list of <see cref="WorkItem"/> objects representing all the open bugs.</returns>
    public async Task<IList<WorkItem>> QueryOpenBugs(string project)
    {
        var credentials = new VssBasicCredential(string.Empty, this.personalAccessToken);
        var wiql = new Wiql()
        {
            Query = "Select [Id] " +
                    "From WorkItems " +
                    "Where [Work Item Type] = 'Bug' " +
                    "And [System.TeamProject] = '" + project + "' " +
                    "And [System.State] <> 'Closed' " +
                    "Order By [State] Asc, [Changed Date] Desc",
        };

        using (var httpClient = new WorkItemTrackingHttpClient(this.uri, new VssCredentials(credentials)))
        {
            try
            {
                var result = await httpClient.QueryByWiqlAsync(wiql).ConfigureAwait(false);
                var ids = result.WorkItems.Select(item => item.Id).ToArray();

                if (ids.Length == 0)
                {
                    return Array.Empty<WorkItem>();
                }

                var fields = new[] { "System.Id", "System.Title", "System.State" };
                return await httpClient.GetWorkItemsAsync(ids, fields, result.AsOf).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error querying work items: " + ex.Message);
                return Array.Empty<WorkItem>();
            }
        }
    }

    /// <summary>
    /// Execute a WIQL (Work Item Query Language) query to print a list of open bugs.
    /// </summary>
    /// <param name="project">The name of your project within your organization.</param>
    /// <returns>An async task.</returns>
    public async Task PrintOpenBugsAsync(string project)
    {
        var workItems = await this.QueryOpenBugs(project).ConfigureAwait(false);
        Console.WriteLine("Query Results: {0} items found", workItems.Count);

        foreach (var workItem in workItems)
        {
            Console.WriteLine(
                "{0}\t{1}\t{2}",
                workItem.Id,
                workItem.Fields["System.Title"],
                workItem.Fields["System.State"]);
        }
    }
}

Résolution des problèmes

Lorsque vous utilisez Azure DevOps par programmation, vous pouvez rencontrer des problèmes liés à l’exécution des requêtes, à l’utilisation des paramètres ou aux surcharges de méthode. Cette section fournit des conseils sur les problèmes courants, leurs causes et la façon de les résoudre efficacement. En comprenant ces étapes de résolution des problèmes, vous pouvez garantir une intégration plus fluide et éviter les erreurs d’exécution.

Problèmes courants

  • Instanciation incorrecte de l’objet Wiql: vérifiez que l’objet Wiql est correctement instancié et contient une requête valide.
  • Utilisation incorrecte des paramètres facultatifs : vérifiez que les paramètres facultatifs sont transmis correctement, en particulier s’ils sont null.
  • Syntaxe de requête non valide : vérifiez que la requête dans l’objet Wiql est valide et correspond au format attendu.

RuntimeBinderException

Lorsque vous travaillez avec la QueryByWiqlAsync méthode dans Azure DevOps, vous pouvez rencontrer un RuntimeBinderException. Cette exception se produit généralement lorsque les arguments passés à la méthode ne correspondent à aucune de ses surcharges. Comprendre la signature de la méthode et garantir une utilisation appropriée des paramètres peut aider à résoudre ce problème.

Erreur :
RuntimeBinderException: cette exception se produit lorsque les arguments passés à la QueryByWiqlAsync méthode ne correspondent à aucune des surcharges de la méthode.

Résolution :
Vérifiez que les paramètres passés à la méthode sont des types corrects et dans l’ordre correct. La signature de méthode est la suivante :

public virtual Task<WorkItemQueryResult> QueryByWiqlAsync(
    Wiql wiql,
    bool? continueOnError = null,
    int? top = null,
    object userState = null,
    CancellationToken cancellationToken = default(CancellationToken));

Exemple de code avec une utilisation correcte

L’extrait de code suivant illustre l’utilisation correcte de la QueryByWiqlAsync méthode, ce qui garantit que les paramètres sont correctement définis :

using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
using System;
using System.Threading.Tasks;
public async Task QueryWorkItemsAsync(WorkItemTrackingHttpClient client)
{
    var wiql = new Wiql()
    {
        Query = "SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = 'YourProjectName'"
    };

    try
    {
        var result = await client.QueryByWiqlAsync(wiql);
        foreach (var workItem in result.WorkItems)
        {
            Console.WriteLine($"Work Item ID: {workItem.Id}");
        }
    }
    catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex)
    {
        Console.WriteLine($"Error: {ex.Message}");
    }
}

Explication du code

  • Créez un Wiql objet : l’objetWiql contient la requête pour extraire des éléments de travail.
  • Appel QueryByWiqlAsync: passez l’objet Wiql à la méthode.
  • Gérer les exceptions : attrapez les exceptions et consignez le message d’erreur pour le débogage.

En suivant cette approche, vous pouvez garantir une utilisation appropriée de la QueryByWiqlAsync méthode et éviter les problèmes courants tels que RuntimeBinderException.