user4382587
user4382587

Reputation:

Unable to create new OneDrive folder under root with Microsoft.Graph REST API

I am able to create folders under existing folders but not under the root. I tried URLs with the id of the root and with several variants of the path syntax e.g. "root:/./:", but none of them creates the folder.

I would like to see an example of creating a folder under the root in the docu of the Microsoft.Graph REST API. This could save a lot of time.

Thanks for any answer!

Here is my code:

public static async Task<GameStorageItem> CreateFolderAsync(string parentId, string parentPath, 
                                                                string name)
    {
        var obj = new JObject
        {
            { "name", name },
            { "folder", new JObject() },
            { "@microsoft.graph.conflictBehavior", "fail" }
        };
        dynamic json;
        string content;
        if (parentId == "root")
        {
            content = await MicrosoftAccount.PerformHttpRequestAsync(HttpMethod.Get,
                                             $"me/drive", obj);
            json = JValue.Parse(content);
            parentId = json.id;

            //parentId = "root:./:";
        }
        content = await MicrosoftAccount.PerformHttpRequestAsync(HttpMethod.Post, $"me/drive/items/{parentId}/children", obj);
        json = JValue.Parse(content);
        DateTimeOffset created = json.createdDateTime;
        string id = json.id;
        var folder = new GameStorageFolder(name, $"{parentPath}/{name}", id, created, false);
        return folder;
    }
public static async Task<string> PerformHttpRequestAsync(HttpMethod method, string request, 
                                                             JObject json = null)
    {
        if (__authResult == null || await ValidateTokenAsync(5) == false)
        {
            try
            {
                await SignInAsync();
                __authResult = await __client.AcquireTokenSilent(scopes,
                                     __account).ExecuteAsync();
            }
            catch (MsalUiRequiredException)
            {
                //A MsalUiRequiredException happened on AcquireTokenSilentAsync. 
                //This indicates you need to call AcquireTokenAsync to acquire a token
                try
                {
                    //User must consent
                    __authResult = await __client.AcquireTokenInteractive(scopes)
                                         .ExecuteAsync();
                }
                catch (MsalException ex)
                {
                    //Error acquiring token
                    throw ex;
                }
            }
            catch (Exception ex)
            {
                //Error acquiring token silently
                throw ex;
            }
        }
        var builder = new UriBuilder(__graphUrl + request);
        return await PerformHttpRequestWithTokenAsync(method, builder.Uri, 
                                                      __authResult.AccessToken, json);
    }
private static async Task<string> PerformHttpRequestWithTokenAsync(HttpMethod method, 
                                      Uri uri, string token, JObject json = null)
    {
        HttpResponseMessage response;
        var httpClient = new HttpClient();

        var request = new HttpRequestMessage(method, uri);
        if (json != null)
        {
            request.Content = new StringContent(json.ToString(), Encoding.UTF8, 
                                                "application/json");
        }
        //Add the token in Authorization header
        request.Headers.Authorization = 
            new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);

        response = await httpClient.SendAsync(request);
        return await response.Content.ReadAsStringAsync();
    }

Upvotes: 0

Views: 1147

Answers (2)

Brad
Brad

Reputation: 4202

You have three different options - I'll just show them as the request and let you translate it to code:

Option 1 - POST to children

POST ../me/drive/root/children
{
  "name": "foo",
  "folder": {}
}

Option 2 - PUT to child

PUT ../me/drive/root/children/foo
{
  "folder": {}
}

Option 3 - PUT to path

PUT ../me/drive/root:/foo
{
  "folder": {}
}

Note that all of these URLs reference the root, and then use different mechanisms to create a folder under it.

Upvotes: 1

Joey Phillips
Joey Phillips

Reputation: 1625

OneDrive root resources

When addressing a Microsoft Graph root resource, your app can address OneDrive resources using the following paths:

  1. /drives - List drive resources available to the authenticated user.
  2. /drives/{drive-id} - Access a specific drive by its ID.
  3. /drives/{drive-id}/root/children - List items in the root of a specific drive.
  4. /drive/items/{item-id} - Access a driveItem by its ID.
  5. /drive/special/{special-id} - Access a known folder by its known name.
  6. /shares/{share-id} - Access a driveItem by its shareId or a sharing URL

Path-based addressing within a drive

A driveItem can be addressed by either a unique identifier or where that item exists in the drive's hierarchy (i.e. user path). Within an API request, a colon can be used to shift between API path space and user path space. This syntax is valid for any driveItem addressed via the API space.

You can also transition back to API path space by using a colon at the end of the file system path space. Ensure user data within the URL follows the addressing and path encoding requirements.

  1. /drive/root:/path/to/file - Access a driveItem by path under the root.
  2. /drive/items/{item-id}:/path/to/file - Access a driveItem by its path relative to another item.
  3. /drive/root:/path/to/folder:/children - List children when accessing by path relative to the drive root.
  4. /drive/items/{item-id}:/path/to/folder:/children - List children when accessing by path relative to another item.

https://learn.microsoft.com/en-us/onedrive/developer/rest-api/?view=odsp-graph-online .

Upvotes: 0

Related Questions