Search code examples
restapitfsputazure-devops-rest-api

Update wiki page of tfs by calling rest-api


I want to update an already existing wiki page of tfs by using this document: https://learn.microsoft.com/de-de/rest/api/azure/devops/wiki/pages/create%20or%20update?view=azure-devops-rest-4.1

Creating a new wiki-page (with content) is no problem. That is working fine. But I want to edit an existing one. The tfs-documentation says that the only difference in API call is to use an "If-Match"-header (see section Request Header).

Here I have 3 situations:

  • Using no "If-Match"-Header or an empty: Get a "412 Precondition Failed" error.
  • Using a "If-Match"-Header with random value: Get a "400 Bad Request" error.
  • Using a "If-Match"-Header with exactly 40 characters (like the version-hash of the page-revision (e.g. '09f62be600a3b6d36d21b294dbb00921a5ba03ec')): Again "412 Precondition Failed" error.

I think the revision-hash (40 characters) should be a good way because the error message on non-40-chars returns the 400-error.

But it did not work? Has anyone an idea which id tfs is wanting? I used Postman and C# to update by API. Below you can see my example code:

var handler = new HttpClientHandler()
{
    UseDefaultCredentials = true,
    UseProxy = false,
};
    
var client = new HttpClient(handler);
client.BaseAddress = new Uri(".../pages/pagename" + "?api-version=4.1");
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
    
var putContent = new StringContent("{ \"content\": \"New content for page\" }", Encoding.UTF8, "application/json");
    
client.DefaultRequestHeaders.TryAddWithoutValidation("If-Match", "09f62be600a3b6d36d21b294dbb00921a5ba03ec");
    
var responseTask = client.PutAsync(client.BaseAddress, putContent);
    
var result = responseTask.Result;
var content = result.Content.ReadAsStringAsync().Result;
    
var code = result.StatusCode;
var body = content;

Solution

  • According to the Create or Update Wiki API, if we want to edit the wiki page,If-Match header is required. The value of If-Matchth is the wiki page ETag.

    ETags can also be used for optimistic concurrency control, as a way to help prevent simultaneous updates of a resource from overwriting each other

    so we need to get the wiki Etag before update. Please have a try to change the code as following:

    var baseUrl = "xxxxx";
    var handler = new HttpClientHandler()
                {
                    UseDefaultCredentials = true,
                    UseProxy = false,
                };
    
    var client = new HttpClient(handler)
                {
                    BaseAddress = new Uri(baseUrl)
                };
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", "YourToken");
    var getResult = client.GetAsync(baseUrl).Result;
    var etag = getResult.Headers.GetValues("ETag");
    var putContent = new StringContent("{ \"content\": \"New content for page\" }", Encoding.UTF8, "application/json");
    client.DefaultRequestHeaders.TryAddWithoutValidation("If-Match", etag);
    var responseTask = client.PutAsync(client.BaseAddress, putContent);
    var result = responseTask.Result;
    var content = result.Content.ReadAsStringAsync().Result;
    

    Test Result:

    enter image description here