Delen via


Werkitems opvragen met zoekopdrachten op programmatische wijze

Azure DevOps Services

Het ophalen van werkitems met behulp van query's is een veelvoorkomend scenario in Azure DevOps Services. In dit artikel wordt uitgelegd hoe u dit scenario programmatisch implementeert met behulp van REST API's of .NET-clientbibliotheken.

Vereisten

Categorie Vereisten
Azure DevOps - Een organisatie.<\br>- Een Persoonlijk Toegangstoken (PAT).
Ontwikkelomgeving Een C#-ontwikkelomgeving. U kunt Visual Studio gebruiken.

Belangrijk

We gebruiken persoonlijke toegangstokens (PAW's) als voorbeeld in dit artikel, maar we raden het gebruik van PAW's niet aan. Zie Richtlijnen voor verificatievoor veiligere verificatiemechanismen.

Een C#-project maken in Visual Studio

Zie de visual Studio C#-programmeerdocumentatie voor informatie over C#-programmering in Visual Studio.

C#-code-inhoud

De volgende taken worden uitgevoerd in het codefragment:

  • Verifiëren
    1. Maak inloggegevens aan met uw persoonlijke toegangstoken (PAT).
    2. Genereer de software client met behulp van de inloggegevens.
  • De werkitems ophalen
    1. Maak de query die u wilt gebruiken.
    2. Haal de resultaten voor die query op.
    3. Haal elk van de werkitems op via id.

C#-codefragment

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

Problemen oplossen

Wanneer u programmatisch met Azure DevOps werkt, kunnen er problemen optreden met betrekking tot het uitvoeren van query's, parametergebruik of overbelasting van methoden. In deze sectie vindt u richtlijnen voor veelvoorkomende problemen, de oorzaken ervan en hoe u ze effectief kunt oplossen. Door deze stappen voor probleemoplossing te begrijpen, kunt u een soepelere integratie garanderen en runtimefouten voorkomen.

Veelvoorkomende problemen

  • Onjuiste instantiëring van het Wiql object: zorg ervoor dat het object correct wordt geïnstantieerd en dat het Wiql een geldige query bevat.
  • Onjuist gebruik van optionele parameters: controleer of optionele parameters correct worden doorgegeven, met name als ze null zijn.
  • Ongeldige querysyntaxis: zorg ervoor dat de query in het Wiql object geldig is en overeenkomt met de verwachte indeling.

RuntimeBinderException

Wanneer u met de QueryByWiqlAsync-methode werkt in Azure DevOps, kunt u een RuntimeBinderException tegenkomen. Deze uitzondering treedt meestal op wanneer de argumenten die aan de methode worden doorgegeven, niet overeenkomen met een van de overbelastingen. Inzicht in de handtekening van de methode en ervoor zorgen dat het juiste parametergebruik dit probleem kan oplossen.

Fout:
RuntimeBinderException: Deze uitzondering treedt op wanneer de argumenten die aan de QueryByWiqlAsync methode worden doorgegeven, niet overeenkomen met een van de overbelastingen van de methode.

Oplossing:
Zorg ervoor dat de parameters die aan de methode worden doorgegeven, van de juiste typen en in de juiste volgorde zijn. De methode-signatuur is als volgt:

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

Voorbeeldcode met correct gebruik

Het volgende codefragment laat het juiste gebruik van de QueryByWiqlAsync methode zien, zodat de parameters correct zijn gedefinieerd:

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

Uitleg van de code

  • Wiql Een object maken: het Wiql object bevat de query om werkitems op te halen.
  • Aanroep QueryByWiqlAsync: Geef het Wiql object door aan de methode.
  • Uitzonderingen afhandelen: RuntimeBinderException opvangen en het foutbericht voor foutopsporing vastleggen.

Door deze aanpak te volgen, kunt u het juiste gebruik van de QueryByWiqlAsync methode garanderen en veelvoorkomende problemen voorkomen, zoals RuntimeBinderException.