MS Graph API: Copying a driveItem using PostAsync does not return a result

Viewed 344

I want to copy a file from one folder in a Sharepoint document library to another folder in the library.

I'm using

Task<DriveItem> copyDriveItemTask = _graphClient.Sites.Root.Lists[_nameOfDocLib].Drive.Root.ItemWithPath(_pathToItemLocation)
                                    .Copy(newName, parentReference).Request().PostAsync();
copyDriveItemTask.Wait();

After the copyDriveItemTask returns, its result is null! Trying to access the new file does not work every time. I think copying the file has not been finished at this time. If I walkthrough step by step in debug mode it works all the time, giving the Sharepoint server enough time to complete his copy actions.

According to Graph.Api's http documentation the PostAsync call should return with a response containing a link to retrieve the progress of the copy process.

In the c# documentation such a result is missing. The PostAsync here is called with simple await!

According to the Graph.Api's IDriveItemCopyRequest interface PostAsync should return a Task<DriveItem>.

I think the c# PostAsync call does not wait until the file is entirely copied. It returns immediately as it is described for the http variant (missing the link to retrieve the progress). But at this time there is no DriveItem that can be returned. So it ends up with a result null.

Whether my explanation is correct or not, in the c# variant I have no chance to determine, if the copy process has terminated or not.

Better explanations, other help or even a solution are appreciated ...

Kalle

2 Answers
 public class GraphMonitorResponseModel
  {
    public float PercentageComplete { get; set; }
    public string ResourceId { get; set; }
    public string Status { get; set; }
  }
var res = await _graphClient.Sites.Root.Lists[_nameOfDocLib]
          .Drive.Root.ItemWithPath(_pathToItemLocation)
          .Copy(newName, parentReference).Request().PostAsync();

var resMon = await getStatus();
while (resMon.Status != "completed")
{
        if (resMon.Status == "failed") //do what you need to and return.
        if (resMon.Status == "in-progress") //do what you need to.
        await Task.Delay(100);
        resMon = await getStatus();
}
//Copy will be complete or failed if the code reaches this point.

async Task<GraphMonitorResponseModel> getStatus()
        => JsonConvert.DeserializeObject<GraphMonitorResponseModel>
           (await _http.GetStringAsync(res.Headers.Location));

Ref: https://docs.microsoft.com/en-us/graph/api/driveitem-copy?view=graph-rest-1.0&tabs=http https://docs.microsoft.com/en-us/graph/api/resources/asyncjobstatus?view=graph-rest-beta&viewFallbackFrom=graph-rest-1.0

To see result of postAsync method in debug execute 2 steps. Screenshot: PostAsyn

  1. return HttpResponseMessage from method with postAsync:

    private static async Task<HttpResponseMessage> methodWithPostAsync(){
    ...
    response = await client.PostAsync(url, data);
    return response
    }
    
  2. call method and wait for response message status:

    Task<HttpResponseMessage> content= methodWithPostAsync();
    while (!content.IsCompleted)
    {
        Console.WriteLine("busy");
        System.Threading.Thread.Sleep(1000);
    }
    
Related