title: TFS API: Clone Build Definition Environment
body: <p>I want to clone an existing environment within a build definition.</p>
  
  <p>This is possible through the TFS GUI, but it doesn't seem like the API natively supports it.</p>
  
  <p>So far, I've tried the following (in PowerShell):</p>
  
  <h1>Download build definition and deserialize</h1>
  
  <pre><code>[void][System.Reflection.Assembly]::LoadFile("$pwd\Newtonsoft.Json.dll")
  
  $TargetDefinitionName = "Name"
  
  $TargetDefinitionID = ($DefinitionsOverview | Where-Object { $_.name -eq $TargetDefinitionName } | Select-Object -First 1).id
  
  $TargetDefinitionURL = "$TfsUri/$TargetDefinitionID"
  
  $TargetDefinitionJSON = Invoke-WebRequest -Uri "$TargetDefinitionURL" -UseDefaultCredentials
  
  $DeserializedBuildDefinition = [Newtonsoft.Json.JsonConvert]::DeserializeObject($TargetDefinitionJSON.Content)
  
  $DeserializedBuildDefinition.ToString()
  </code></pre>
  
  <h1>Duplicate JSON block that represents environment, change unique properties</h1>
  
  <pre><code>$NewEnvironmentString = $DeserializedBuildDefinition.environments[4].ToString()
  
  $DeserializedBuildDefinition.environments.Add(5)
  
  $DeserializedBuildDefinition.environments[5] = $NewEnvironmentString 
  
  $DeserializedBuildDefinition.environments[5].name.value = "NewEnvironment"
  
  $DeserializedBuildDefinition.environments[5].rank.value = "6"
  
  $DeserializedBuildDefinition.environments[5].id.value = "1665"
  
  $DeserializedBuildDefinition.revision.value = "20"
  </code></pre>
  
  <h1>Serialize JSON and post back (with new environment)</h1>
  
  <pre><code>$SerializedBuildDefinition = [Newtonsoft.Json.JsonConvert]::SerializeObject($DeserializedBuildDefinition)
  
  $PostData = [System.Text.Encoding]::UTF8.GetBytes($SerializedBuildDefinition)
  
  $Headers = @{ "Accept" = "api-version=2.0-preview" }
  
  $Response = Invoke-WebRequest -UseDefaultCredentials -Uri 
  $TargetDefinitionURL -Headers $Headers `
            -Method Put -Body $PostData -ContentType "application/json"
  
  $Response.StatusDescription
  </code></pre>
  
  <p>PROBLEM: $Response.StatusDescription gives "OK," but no new environment appears in the build definition.</p>
  
  <p>One thought is that, in addition to 'name,' 'ID,' and 'rank, there are other values that need to be unique per environment that I'm missing.</p>
  
  <p>I've also tried cloning the environment manually, saving the JSON representation of the definition, deleting the environment, and posting the JSON back. The new environment still doesn't show up.</p>
  
  <p>Any help would be appreciated.</p>