akshay Sharma
akshay Sharma

Reputation: 57

Azure pipeline rest api is not taking parameters of type list in request body

Lets say I have a build pipeline with following definition:

    parameters:
  - name: "BoxNames"
    displayName: 'List of box names'
    type: object
    default:
      - name1
      - name2
  - name: 'id'
    displayName: 'subscrption id'
    type: string
    default: 'xxxx'
    values:
    - xxxx
    - yyyy
    

Now I am trying to queue a build for this pipeline in C# by rest api with following request body:

var requestBody = new
{
    definition = new
    {
        id = 234,
    },
    project = new
    {
        id = xxxx
    },
    sourceBranch = "main",
    templateParameters = new
    {
        BoxNames = new List<string> { "name1" },
        id = "yyyy"
    }
};

This is queuing the build for me but it is taking the templateParameters as default parameters, not one I am sending in the request body.

I have another pipeline with string parameters and no list values, that is picking the correct parameters by same way.

What can be the problem here?

Upvotes: 0

Views: 113

Answers (1)

wade zhou - MSFT
wade zhou - MSFT

Reputation: 8180

I followed your yaml, and C# snippet, i output the requestbody and response content, it will report the error Unable to convert from Array to String. Value: Array".

enter image description here

you have defined object type for parameter BoxNames in yaml, but in C# script, it's string format.

To fix the error, you can directly define value in request body:

                templateParameters = new
                {
                    BoxNames = "name6",
                    id = "yyyy"
                }

The full C# script:

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Net.Http.Headers;

class Program
{
    static async Task Main(string[] args)
    {
        var personalAccessToken = "PAT";                
        string credentials = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", personalAccessToken)));

        using (var client = new HttpClient())
        {
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);

            var requestBody = new
            {
                definition = new { id = "410" },
                sourceBranch = "refs/heads/main",
                templateParameters = new
                {
                    BoxNames = "name6",
                    id = "yyyy"
                }
            };

            var serializedRequestBody = JsonConvert.SerializeObject(requestBody);
            Console.WriteLine($"Request Body: {serializedRequestBody}");

            var content = new StringContent(JsonConvert.SerializeObject(requestBody), Encoding.UTF8, "application/json");

            
            var url = $"https://dev.azure.com/{org}/{project}/_apis/build/builds?api-version=7.1-preview.7";
            var response = await client.PostAsync(url, content);

            Console.WriteLine($"Response Status Code: {response.StatusCode}");
            Console.WriteLine($"Response Content: {await response.Content.ReadAsStringAsync()}");

            response.EnsureSuccessStatusCode();
            Console.WriteLine("Build queued successfully.");
        }
    }
}

The devops yaml:

trigger: none

parameters:
  - name: "BoxNames"
    displayName: 'List of box names'
    type: object
    default:
      - name1
      - name2
  - name: 'id'
    displayName: 'subscrption id'
    type: string
    default: 'xxxx'
    values:
      - xxxx
      - yyyy

pool:
  vmImage: ubuntu-latest

steps:
- script: |
    echo ${{ parameters.BoxNames }}
    echo ${{ parameters.id }}
  displayName: 'Run a one-line script'

THe C# trigger result:

enter image description here

To pass mutiple strings, you can use string type parameter in yaml:

trigger: none

parameters:
  - name: "BoxNames"
    displayName: 'List of box names'
    type: string
    default: name1,name2

  - name: 'id'
    displayName: 'subscrption id'
    type: string
    default: 'xxxx'
    values:
      - xxxx
      - yyyy


pool:
  vmImage: ubuntu-latest

steps:
- ${{ each name in split(parameters.BoxNames, ',')}}:
  - script:  echo ${{ name }}
- script: |
    echo ${{ parameters.id }}
  displayName: 'Run a one-line script'

In the C# script, the response body as below:

            var requestBody = new
            {
                definition = new { id = "410" },
                sourceBranch = "refs/heads/main",
                templateParameters = new
                {
                    BoxNames ="name6,name7,name8",
                    id = "yyyy"
                }
            };

The pipeline is triggered with output for each value:

enter image description here

Upvotes: 0

Related Questions