pnp / pnpcore

The PnP Core SDK is a modern .NET SDK designed to work for Microsoft 365. It provides a unified object model for working with SharePoint Online and Teams which is agnostic to the underlying API's being called
https://aka.ms/pnp/coresdk/docs
MIT License
296 stars 191 forks source link

GetFileByServerRelativeUrlAsync() - 404 File not found #1077

Closed Gareth064 closed 1 year ago

Gareth064 commented 1 year ago

Category

Describe the bug

When trying to get a document using it's ServerRelativeUrl, and part of the Url path includes a space character, I get an error saysing the document couldn't be found.

Steps to reproduce

           var documentURL = "https://tenant.sharepoint.com/sites/ECM_COM/Customer%20Account/2022-09/scs_doc_01.docx";
            var site = UrlParser.GetSPOSiteFromPath(documentURL); //This returns 'ECM_COM'
            using var pnpContext = await pnpContextFactory.CreateAsync(site); // creates context and works
            var path = UrlParser.GetUrlPath(documentURL); // this returns /sites/ECM_COM/Customer%20Account/2022-09/scs_doc_01.docx

            var document = await pnpContext.Web.GetFileByServerRelativeUrlAsync(path,
                f => f.ListItemAllFields.QueryProperties(li => li.All));

Results in exception

HttpResponseCode: 404
Code: Microsoft.SharePoint.SPException
Message: The file /sites/ECM_COM/Customer%20Account/2022-09/scs_doc_01.docx does not exist.
ClientRequestId: ab128fa0-d0ed-6000-04ce-00962180e300
SPClientServiceRequestDuration: 26
X-SharePointHealthScore: 1
X-SP-SERVERSTATE: ReadOnly=0

PnP.Core.SharePointRestServiceException: SharePoint Rest service exception
   at PnP.Core.Services.BatchClient.ExecuteSharePointRestInteractiveAsync(Batch batch)
   at PnP.Core.Services.BatchClient.ExecuteSharePointRestBatchAsync(Batch batch)
   at PnP.Core.Services.BatchClient.ExecuteBatch(Batch batch)
   at PnP.Core.Model.BaseDataModel`1.BaseRetrieveAsync(ApiCall apiOverride, Func`2 fromJsonCasting, Action`1 postMappingJson, Expression`1[] expressions)
   at PnP.Core.Model.SharePoint.Web.GetFileByServerRelativeUrlAsync(String serverRelativeUrl, Expression`1[] expressions)
   at CHG.SPO.FilingService.Brokers.Apis.SharePointOnlineBroker.GetDocumentFromUrl(String documentURL)

Expected behavior

A document is found and returned

Environment details (development & target environment)

Additional context

You can see that the path to the document includes a Document Library named "Customer Account" which has a space in it. I believe this is what is causing the issue. If I replicate this with a document library name "CustomerAccount", without the space, then it returns fine.

jansenbe commented 1 year ago

Thanks for reporting this @Gareth064, I'll have a look and let you know

jansenbe commented 1 year ago

@Gareth064 : You've found a bug: when the input string already contains %20 the encoding goes wrong (see below). Problem is fixed and will appear in the next nightly (version 1.8.79+) but you can also easily workaround by adding .Replace("%20", " ") on the method input. Closing the issue, please re-open or create a new one in case the problem persists.

string serverRelativeUrl = "/sites/prov-1/I have%20SPaces/CV%20Caro%20Jansen%20r0846424%20.pdf";
string encodedServerRelativeUrl = WebUtility.UrlEncode(serverRelativeUrl.Replace("'", "''")/*.Replace("%20", " ")*/).Replace("+", "%20");

Console.WriteLine(encodedServerRelativeUrl);

//with fix, works: %2Fsites%2Fprov-1%2FI%20have%20SPaces%2FCV%20Caro%20Jansen%20r0846424%20.pdf
//without fix, fails: %2Fsites%2Fprov-1%2FI%20have%2520SPaces%2FCV%2520Caro%2520Jansen%2520r0846424%2520.pdf
Gareth064 commented 1 year ago

@jansenbe Thank you very much for you're quick response and fix. Very much appreciated. And as you suggested, the workaround has worked a treat.