SharePoint CSOM Upload File Access Denied Error

Simple process, using a .Net Web App, create a local file and upload it to SharePoint. I thought the service account I was using had ampel permissions to the Site, but for it didnt… For testing, I granted the seveice account Full Control at the Web App level (user policy), site collection admin, and more. Nothing worked.

Sample of the code I was using:

            ClientContext ctxH = new ClientContext(hURL);
            Web siteH = ctxH.Web;
            ctxH.Load(siteH);
            ctxH.ExecuteQuery();

            List _library = siteH.Lists.GetByTitle("Drop Off Library");

            Folder _oFolder = siteH.GetFolderByServerRelativeUrl(siteH.ServerRelativeUrl.TrimEnd('/') + "/" + "DropOffLibrary");
            ctxH.Load(_oFolder);
            ctxH.ExecuteQuery();

            FileStream fileStream = System.IO.File.OpenRead(fileName);
            FileCreationInformation fileInfo = new FileCreationInformation();
            fileInfo.ContentStream = fileStream;
            fileInfo.Overwrite = true;
            fileInfo.Url = destFileName;

            Microsoft.SharePoint.Client.File _oFile = _oFolder.Files.Add(fileInfo);
            ctxHub.Load(_oFile);
            ctxHub.ExecuteQuery();

Quick and simple fix:
Grant your account / service account Design permissions to the Site/Web where you are uploading files.

Error at the web level:
C:\Windows\TEMP\tmp28E2.tmp: Access denied. You do not have permission to perform this action or access this resource.

ULS errors:
Permission check failed. Asking for 0x00040002, have 0x1B00C0310EF
Access denied.
System.UnauthorizedAccessException: Access denied., StackTrace:
Exception : System.UnauthorizedAccessException: Access denied.
Exception occured in scope Microsoft.SharePoint.SPFileCollection.Add. Exception=System.UnauthorizedAccessException: Access denied.
Original error: System.UnauthorizedAccessException: Access denied.
SocialRESTExceptionProcessingHandler.DoServerExceptionProcessing – SharePoint Server Exception [System.UnauthorizedAccessException: Access denied.
Throw UnauthorizedAccessException instead of SPUtilityInternal.Send401 for client.svc request.

Uploading Files to SharePoint 2016 Using ListData.svc

Update
Another issue we ran into was related to client machines having an outdated cert. Once the updated cert was published to SharePoint, the client machines downloaded the new cert and were able to upload to SharePoint.

Ran into a small issue when testing some code for a SharePoint 2010 to SharePoint 2016 migration.

With SharePoint 2010, the following code sample would work to upload files to a library.

//ServRef is a Service Reference to _vti_bin/ListData.svc
string sharePointSvc = "https://sp2016.some.url/sites/random/_vti_bin/ListData.svc";

            using (FileStream file = File.Open(@"C:\test1.docx", FileMode.Open))
            {
                ServRef.RandomDataContext ctx = new ServRef.RandomDataContext(new Uri(sharePointSvc));

                ctx.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;

                string filename = Path.GetFileNameWithoutExtension(file.Name);
                string path = "/sites/random/dropofflibrary/" + Path.GetFileName(file.Name);
                string contentType = "Interest Summary";

                ServRef.DropOffLibraryItem documentItem = new ServRef.DropOffLibraryItem()
                {
                    ContentType = contentType,
                    Name = filename,
                    Title = filename
                };

                ctx.AddToDropOffLibrary(documentItem);
                ctx.SetSaveStream(documentItem, file, false, contentType, path);

                try
                {
                    ctx.SaveChanges();
                }
                catch (Exception ex)
                {
                    var err = ex.Message;
                    throw;
                }
            } 

When trying to use this same code with SharePoint 2016, I was receiving the following Errors:
Output error: An error occurred while processing this request.

Errors from Fiddler:
Auth:
No Proxy-Authenticate Header is present.

No WWW-Authenticate Header is present.

Caching:

Under RFC2616, HTTP/500 responses will not be cached regardless of what caching headers may be present. HTTP/1.1 Cache-Control Header is present: no-cache

This response does not specify explicit HTTP Cache Lifetime information and does not specify a Last-Modified date. Heuristic expiration is typically based on Last-Modified date. Lacking Last-Modified, this response may be revalidated on every use or once per browsing session, depending on the browser configuration.

This response contains neither an ETAG nor a Last-Modified time. This will prevent a Conditional Revalidation of this response.

FIX
For SharePoint 2016, the upload process required that the Path property be populated.

//ServRef is a Service Reference to _vti_bin/ListData.svc
string sharePointSvc = "https://sp2016.some.url/sites/random/_vti_bin/ListData.svc";

            using (FileStream file = File.Open(@"C:\test1.docx", FileMode.Open))
            {
                ServRef.RandomDataContext ctx = new ServRef.RandomDataContext(new Uri(sharePointSvc));

                ctx.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;

                string filename = Path.GetFileNameWithoutExtension(file.Name);
                string path = "/sites/random/dropofflibrary/" + Path.GetFileName(file.Name);
                string contentType = "Interest Summary";

                ServRef.DropOffLibraryItem documentItem = new ServRef.DropOffLibraryItem()
                {
                    Path = path,
                    ContentType = contentType,
                    Name = filename,
                    Title = filename
                };

                ctx.AddToDropOffLibrary(documentItem);
                ctx.SetSaveStream(documentItem, file, false, contentType, path);

                try
                {
                    ctx.SaveChanges();
                }
                catch (Exception ex)
                {
                    var err = ex.Message;
                    throw;
                }
            }