An Odd Behavior with the ServerRelativeUrl Property in CSOM

I was attempting to build a query using the ClientContext.LoadQuery method because it has some performance benefits that make it a useful approach for querying SharePoint. I was attempting to query a specific list using the ServerRelativeUrl property on the RootFolder on the List, but I only had the site-relative URL of the list. So I was combining that partial URL with the ServerRelativeUrl property from the Site property on the ClientContext to construct the full server relative URL. My queries returned no items.

The server-relative URL of the list’s RootFolder was coming back as:
/sites/dev/lists/MyList/

The site-relative URL that I had for the list was:
/lists/MyList/

And the ServerRelativeUrl coming back from the Site on the ClientContext was:
/Sites/Dev/

This may better point out the issue:
/sites/dev/lists/MyList/
/Sites/Dev/lists/MyList/

So the casing of the URL coming back from the Site object was incorrect, and unfortunately there is no way to normalize casing when using the ClientContext.LoadQuery method because it doesn’t support the ToUpper() or ToLower() methods in queries. But my question is, why was the URL casing different on the ServerRelativeUrl properties on the Site and the RootFolder instances? You would think that SharePoint would be nice enough to provide the values using the same casing.

Well, it turns out the issue is simple – the URL that is populated into the Site object matches the casing used to construct the ClientContext instance. My code looked like this:

var context = new ClientContext(“https://someserver/Sites/Dev/”);

Changing the URL in the ClientContext constructor fixed my issue. Oddly enough, if you attempt to access the ServerRelativeUrl property on the ClientContext‘s Site property without loading it, then you will get an error about how the property has not yet been loaded. So you have to make a round trip to the server just so it can ultimately use the URL that you already provided in client code. Thanks SharePoint.

Unfortunately, this is not the only location where this shows up. This is also an issue when you call the Web.GetFolderByServerRelativeUrl method and then request the ServerRelativeUrl of the folder. You’ll actually get back exactly what you passed into the GetFolderByServerRelativeUrl method. And in this scenario it’s not just casing, if you pass in a URL to a file in the folder, the folder will come back successfully but the ServerRelativeUrl property will be initialized with the URL to the file and not just that of the folder.

I’m sure there are other places where this crops up as well, so be forewarned.