skip to Main Content

We have multiple SharePoint sites, and our application is registered on the domain. Currently, we are trying to fetch documents from SharePoint using a client ID and secret, but we are encountering issues. We have used the GraphClient but receive empty objects for the root, drives, and item lists. We have also ensured that all permissions are granted at the application level. Here is the code snippet : (code developed in .net 8 and we have used latest Microsoft.Identity.Client Nuget package)

public async Task<string> GetAccessTokenAsync()
{
    string[] scopes = { "https://graph.microsoft.com/.default" };

    var clientSecretCredential = new ClientSecretCredential(
            tenantId, clientId, clientSecret);

    var graphClient = new GraphServiceClient(clientSecretCredential, scopes);

    // Retrieve the files from the "My Files" folder (OneDrive root)

    var document = await graphClient.Users["[email protected]"].GetAsync();

    var driveItems = await graphClient.Sites["XXXX-my.sharepoint.com"].GetAsync();

    
    foreach (var items in document.Drive.Items)
    {
        Console.WriteLine(items.Name);
    }
}

How can we retrieve all "My Files" documents using Microsoft Graph?

Test File

2

Answers


  1. In OneDrive My files in my environment is like below:

    enter image description here

    Use the below code to retrieve all "My Files" using Microsoft Graph:

    namespace GraphApiDemo
    {
        class Program
        {
            private static string tenantId = "TenantID";
            private static string clientId = "ClientID";
            private static string clientSecret = "ClientSecret";
            private static string userId = "UserID";
            private static string driveId = "DriveID"; 
    
            public static async Task Main(string[] args)
            {
                try
                {
                    var token = await GetAccessTokenAsync();
                    await RetrieveDriveItemsAsync(token);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("An error occurred: " + ex.Message);
                }
            }
    
            public static async Task<string> GetAccessTokenAsync()
            {
                var scope = "https://graph.microsoft.com/.default";
                var authority = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token";
    
                using (var client = new HttpClient())
                {
                    var request = new HttpRequestMessage(HttpMethod.Post, authority);
                    request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
    
                    var content = new FormUrlEncodedContent(new[]
                    {
                        new KeyValuePair<string, string>("grant_type", "client_credentials"),
                        new KeyValuePair<string, string>("client_id", clientId),
                        new KeyValuePair<string, string>("client_secret", clientSecret),
                        new KeyValuePair<string, string>("scope", scope)
                    });
                    request.Content = content;
    
                    var response = await client.SendAsync(request);
                    response.EnsureSuccessStatusCode();
    
                    var responseContent = await response.Content.ReadAsStringAsync();
                    var tokenResponse = JsonDocument.Parse(responseContent);
                    var accessToken = tokenResponse.RootElement.GetProperty("access_token").GetString();
                    return accessToken;
                }
            }
    
            public static async Task RetrieveDriveItemsAsync(string accessToken)
            {
                using (var client = new HttpClient())
                {
                    var url = $"https://graph.microsoft.com/v1.0/users/{userId}/drives/{driveId}/root/children";
                    var request = new HttpRequestMessage(HttpMethod.Get, url);
                    request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
    
                    var response = await client.SendAsync(request);
    
                    if (!response.IsSuccessStatusCode)
                    {
                        var errorContent = await response.Content.ReadAsStringAsync();
                        Console.WriteLine($"Error: {response.StatusCode} - {response.ReasonPhrase}");
                        Console.WriteLine("Response content:");
                        Console.WriteLine(errorContent);
                        return;
                    }
    
                    var responseContent = await response.Content.ReadAsStringAsync();
    
                    using (JsonDocument doc = JsonDocument.Parse(responseContent))
                    {
                        JsonElement root = doc.RootElement;
                        JsonElement items = root.GetProperty("value");
    
                        Console.WriteLine("Files and folders in the specified drive root folder:");
    
                        foreach (JsonElement item in items.EnumerateArray())
                        {
                            string name = item.GetProperty("name").GetString();
                            Console.WriteLine(name);
                        }
                    }
                }
            }
        }
    }
    

    I got the response successfully like below:

    enter image description here

    • You can also pass var url = $"https://graph.microsoft.com/v1.0/users/{userId}/drive/root/children"; directy if you do not want to pass DriveID.

    Make sure the Microsoft Entra ID application is granted with Files.Read.All application type API permission.

    Login or Signup to reply.
  2. To access user’s drive, you need to call graphClient.Users["[email protected]"].Drive.GetAsync(), your current call graphClient.Users["[email protected]"].GetAsync() returns basic info about the user, but without a drive.

    When iterating drive’s items, you should handle paging and probably iterate through all subfolders.

    If you still prefer using the Graph SDK v5, you can use this helper method to retrieve all files from user’s or SharePoint site’s drive

    public async Task<List<DriveItem>> GetChildItemsAsync(string driveId, string driveItemId, List<DriveItem> allDriveItems)
    {
        var allDriveItemChildren = new List<DriveItem>();
    
        var firstPage = await graphClient.Drives[driveId].Items[driveItemId].Children.GetAsync();
        // if folder has more than 200 items, we need to use PageIterator to retrieve all items
        var pageIterator = PageIterator<DriveItem, DriveItemCollectionResponse>.CreatePageIterator(graphClient, firstPage, driveItem =>
        {
            allDriveItemChildren.Add(driveItem);
            return true;
        });
    
        await pageIterator.IterateAsync();
    
        // recursion: retrieve driveItem for each child
        foreach (var item in allDriveItemChildren)
        {
            allDriveItems.Add(item);
            // only folder has child
            if (item.Folder != null && item.Folder.ChildCount > 0)
            {
                await GetChildItemsAsync(driveId, item.Id, allDriveItems);
            }
        }
        return allDriveItems;
    }
    

    Calling the helper method from main code

    var items = new List<DriveItem>();
    // user's drive
    var drive = await graphClient.Users["[email protected]"].Drive.GetAsync();
    // site's drive (default document library)
    // var drive = await graphClient.Sites["{site_id}"].GetAsync();
    var allDriveItems = await GetChildItemsAsync(drive.Id, "root", items);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search