Benny Yamagata
Benny Yamagata

Reputation: 49

How to fix null value build.Definition in TFS Queue Build REST API call

I am trying to queue a build from my TFS servers using the TFS Rest API nuget package for c#. However, upon sending the request to the server with the JSON:

"definition":{ "id":63 }

I get a 400 response back with the error:

message=Value cannot be null. Parameter name: build.Definition

I think I am sending the JSON correctly, considering before I was getting errors saying it couldnt be deserialized, or that there wasnt a JSON in the first place.

Can someone help me figure out what is causing this error and how to fix it?

For reference and showing what I have already used as help:

Microsoft Documentation

Queue Build using Powershell

Again Queueing a build in powershell

And several other articles (google "queue build tfs rest api c#")

//post request for queuing the build
var client = new RestClient(websiteName);
var request = new RestRequest("_apis/build/builds?ignoreWarnings=true&sourceBuildId=63&api-version=4.0", Method.POST, DataFormat.Json);

Dictionary<string, string> values = new Dictionary<string, string>();
values.Add("{\"definition\"", "{\"id\":63}}");

request.AddHeader("Authorization", "Basic " + Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", "", personalAccessToken))));

request.AddJsonBody(values);
IRestResponse response = client.Execute(request);

Upvotes: 0

Views: 312

Answers (2)

Shayki Abramczyk
Shayki Abramczyk

Reputation: 41625

If you use the Rest API nuget packages, you can use build-in methods to queue a new build, this will much convenient than using HttpClient or other class:

var url = new Uri("http://tfsServer:8080/tfs/MyCollection/");
var connection = new VssConnection(url, new VssCredentials());
var buildServer = connection.GetClient<BuildHttpClient>();           
// Get the list of build definitions.
var  definition = buildServer.GetDefinitionAsync("teamprojectname", 33).Result;

//It requires project's GUID, so we're compelled to get GUID by API.
var res = buildServer.QueueBuildAsync(new Build
{
      Definition = new DefinitionReference
{
Id = definition.Id
},
      Project = definition.Project
});
Console.WriteLine($"Queued build with id: {res.Id}");

If you still want to use the URL to trigger, here is also an example:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://tfsServer:8080/tfs/DefaultCollection/TeamProject/_apis/build/builds?api-version=4.0");
request.Credentials = CredentialCache.DefaultNetworkCredentials;
request.Method = "Post";
request.ContentType = "application/json";
Stream stream = request.GetRequestStream();
string json = "{\"definition\":{\"id\":63}}";
byte[] buffer = Encoding.UTF8.GetBytes(json);
stream.Write(buffer, 0, buffer.Length);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Console.Write(response.StatusCode);
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
     var result = streamReader.ReadToEnd();
}
Console.Read();

Upvotes: 0

Daniel Mann
Daniel Mann

Reputation: 59036

"definition":{ "id":63 } isn't valid JSON.

{ "definition":{ "id":63 } } is.

Don't construct JSON as a string, use ConvertTo-Json on an associative array to turn an appropriately-shaped object into JSON, such as

$body = @{
    definition = @{ 
        id = $definitionId
    }
} | ConvertTo-Json -Depth 100

Upvotes: 1

Related Questions