Use MSGraph to upload a file to Sharepoint

Mark Lam 6 Reputation points
2021-09-10T22:34:57.027+00:00

So I've been using MSGraph to send email using O365 accounts with no problem. I have code that works and understand how MSGraph API so I thought uploading a file to my O365 sharepoint account should be fairly straightforward. The problem I'm getting is on the call to upload the stream I get "access denied error exception"

Code: accessDenied
Message: Access denied
Inner error:
AdditionalData:
date: 2021-09-08T22:14:25
request-id: c7a5d76d-eacf-4f37-9f4f-c90982079201
client-request-id: c7a5d76d-eacf-4f37-9f4f-c90982079201
ClientRequestId: c7a5d76d-eacf-4f37-9f4f-c90982079201

What I'm not clear about is what the site string value should be inside the brackets [ ]. The MS doc isn't clear on this. So after I properly authenticated I can successfully get information on specific Share point site using the code below ( our share point has a site "products" the url is (https://{company}.sharepoint.com/sites/Product.

When I login to my account I can manually upload files with no problem. As I said using this account with MSGraph I can send email with no problem after I get my access token

so this code works fine

var targetSite = await graphclient.Sites.GetByPath("sites/Product", "{companyName}.sharepoint.com").Request().GetAsync();

this returns information on the target site so I'm clearly interfacing with my 0365 account fine

So to upload a file I tried many different ways but I'm always getting the access deny exception

                    uploadedFile = await graphclient.Sites["{companyName}.com,23e84842-1377-473e-ae29-c2289b7eacfb,72d74744-ed95-45a2-ac52-d558fcd6c324"].Drive.Root.ItemWithPath("check1.pdf").Content.Request().PutAsync<DriveItem>(stream4);  

the root.itemWithPath is suppose to be the name of the file after it's uploaded. The Site string inside [ ] is the thing that isn't clear.

I also tried this but also get the same access deny exception.

 var targetSite = await graphclient.Sites.GetByPath("sites/Product", "{company}.com").Request().GetAsync();  


   var targetFolder2 = graphclient.Sites[targetSite.Id].Drive.Root;  

     var pathToFile = @"c:\testdata\check1.pdf";  
                        using (var fileStream = new FileStream(pathToFile, FileMode.Open, FileAccess.Read))  
                        {  
                            var uploadedItem = await targetFolder2  
                              .ItemWithPath("check1.pdf")  
                              .Content  
                              .Request()  
                              .PutAsync<DriveItem>(fileStream);  
                        }  

I tried various different "site" strings but they give me a different exception (invalid URL) so I don't think that right.

sites/{company}.sharepoint.com:/sites/Product:/"
https://graph.microsoft.com/v1.0/sites/{company}.com,/Product:/"]

I have been reading Microsoft doc but no success figuring things out
https://learn.microsoft.com/en-us/graph/api/driveitem-put-content?view=graph-rest-1.0&tabs=csharp

pretty sure it has something to do with permission. Our O365 IT admin and I have been trying different things but no luck

Files.ReadWrite.All, Sites.ReadWrite.All

I'm thinking maybe I have to set my scopes to Sites.ReadWriteAll.?

My current scope may be missing something
//Set the scope for API call to user.read
string[] scopes = new string[] { "user.read", "mail.send", "User.ReadWrite.All"};

SharePoint Server
SharePoint Server
A family of Microsoft on-premises document management and storage systems.
2,216 questions
Microsoft Graph
Microsoft Graph
A Microsoft programmability model that exposes REST APIs and client libraries to access data on Microsoft 365 services.
10,565 questions
SharePoint
SharePoint
A group of Microsoft Products and technologies used for sharing and managing content, knowledge, and applications.
9,606 questions
SharePoint Development
SharePoint Development
SharePoint: A group of Microsoft Products and technologies used for sharing and managing content, knowledge, and applications.Development: The process of researching, productizing, and refining new or existing technologies.
2,664 questions
Microsoft Teams Development
Microsoft Teams Development
Microsoft Teams: A Microsoft customizable chat-based workspace.Development: The process of researching, productizing, and refining new or existing technologies.
2,838 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. MichaelHan-MSFT 18,016 Reputation points
    2021-09-13T02:09:53.767+00:00

    Hi @Mark Lam ,

    Which permission did you use? Application permission or Delegated permission? According to the documentation, you need to have at least Files.ReadWrite for Delegated permission or Files.ReadWrite.All for application to upload files.
    131403-image.png

    To check the scope for your access token, you could use JWT to decode it: https://jwt.ms/


    If an Answer is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


  2. Hunaid Hanfee-MSFT 976 Reputation points
    2021-09-22T16:36:27.87+00:00

    Hello,
    The code you have pasted is having errors. Pasted the code I get from Postman and it should work fine

    var client = new RestClient("https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token");  
    client.Timeout = -1;  
    var request = new RestRequest(Method.POST);  
    request.AddHeader("Content-Type", "application/x-www-form-urlencoded");  
    request.AddParameter("grant_type", "client_credentials");  
    request.AddParameter("client_id", "{clientId}");  
    request.AddParameter("client_secret", "{clientSecret}");  
    request.AddParameter("scope", "https://graph.microsoft.com/.default");  
    IRestResponse response = client.Execute(request);  
    Console.WriteLine(response.Content);  
    

    I can see in your code the URL is wrong it should be just-
    https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token

    I have done directly from Postman many times. So I have attached the screenshot of how I did it.
    134378-image.png
    Give your value for client Id, secret and tenant Id and it should work. Also Admin needs to consent those permissions you have given in app registration. - Get administrator consent