Search code examples
c#sharepointsharepoint-onlinecsom

Can't upload a file to sharepoint site's file directory using CSOM C# console app


I am trying to upload a file to a specific site's file directory in my org's SharePoint. I created an app on https://OrgTenant.sharepoint.com/sites/MySite/_layouts/15/appregnew.aspx. Then, I gave it FullControl permissions to the site on https://OrgTenant.sharepoint.com/sites/MySite/_layouts/15/AppInv.aspx with the XML permissions as

<AppPermissionRequests AllowAppOnlyPolicy="true">
  <AppPermissionRequest Scope="https://OrgTenant.sharepoint.com/sites/MySite" Right="FullControl" />
</AppPermissionRequests>

I took the client ID and Secret from the app creation and used them in the my C# app's code (see below). I am able to connect to the site and pull information from the site, such as lists, and can see the the directory I am trying to load the file to in the List of lists, but get an Access Denied error when trying to upload the file. I can't seem to find any documentation online about why this may be and it has me thoroughly stumped. Let me know if I am missing something or if there are better alternatives to what I am trying to do as I am open to suggestions!

Code:

using Microsoft.SharePoint.Client;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace ProjectName
{
    class SharepointHelper
    {
        public static void LoadFilesToSharepoint()
        {
            string siteUrl = "https://OrgTenant.sharepoint.com/sites/MySite";
            using (var cc = new PnP.Framework.AuthenticationManager().GetACSAppOnlyContext(siteUrl, [My Client ID], [My Client Secret]))
            {
                cc.Load(cc.Web, p => p.Title, p => p.Lists);
                cc.ExecuteQuery();
                Web web = cc.Web;

                string libraryName = "FileLocation";
                string filePath = "C:\\Folder\\testFileforSP.txt";
                List<Microsoft.SharePoint.Client.List> doclist = cc.Web.Lists.ToList();
                
                using (FileStream fs = new FileStream(filePath, FileMode.Open))
                {
                    FileCreationInformation flciNewFile = new FileCreationInformation();

                    flciNewFile.ContentStream = fs;
                    flciNewFile.Url = System.IO.Path.GetFileName(filePath);
                    flciNewFile.Overwrite = true;

                    List docs = web.Lists.GetByTitle(libraryName);
                    Microsoft.SharePoint.Client.File uploadFile = docs.RootFolder.Files.Add(flciNewFile);

                    cc.Load(uploadFile);
                    cc.ExecuteQuery();
                }
            }
        }
    }
}

I get the Access Denied error up on the cc.ExecuteQuery() at the bottom.

I tried giving the app other permissions. I initially gave it Write permissions, then Manage, then Full Control as most examples I saw just gave the app full control so I thought this would help, but it did not. No matter what I did I got Access Denied or Unauthorized access (with lesser permissions).


Solution

  • I was misunderstanding the documentation for giving my app permissions in the AppInv.aspx page where you supply the XML.

    I was giving it this:

    <AppPermissionRequests AllowAppOnlyPolicy="true">
      <AppPermissionRequest Scope="https://OrgTenant.sharepoint.com/sites/MySite" Right="FullControl" />
    </AppPermissionRequests>
    

    Where I should have been giving it this:

    <AppPermissionRequests AllowAppOnlyPolicy="true">
      <AppPermissionRequest Scope="http://sharepoint/content/sitecollection" Right="FullControl" />
    </AppPermissionRequests>
    

    Doing this give your app full control over your site. You don't enter your actual site URL into the XML, there are literal strings you have to enter to apply the permissions you want. It is explained in this documentation. Add-In Permissions