We have a database with absolute (full) links to SharePoint files. If a user wants to download or get checkoutstatus information about the file, our program needs lookup that information in SharePoint.
We have done this easily in the past with the following code:
string url = "http://server/site/documentlibrary/testdoc.docx";
using(SPSite site = new SPSite(url))
{
using(SPWeb web = site.OpenWeb())
{
SPFile file = web.GetFile(url);
}
}
source: http://sacarter.wordpress.com/2011/11/28/retrieve-spfile-object-by-full-url/
Now we want to use the SharePoint Client Object Model instead of the server object model and do the same.
Microsoft.SharePoint.Client.ClientContext clientContext = new Microsoft.SharePoint.Client.ClientContext(@"http://server/site/documentlibrary/testdoc.docx");
Microsoft.SharePoint.Client.File file = clientContext.Web.GetFileByServerRelativeUrl(@"http://server/site/documentlibrary/testdoc.docx");
clientContext.Load(file);
clientContext.ExecuteQuery();
Debug.Print("file: {0}", file.Name);
Debug.Print("checkout status: {0}", file.CheckOutType.ToString());
But then I get the following exception with loading the clientcontext:
Cannot contact site at the specified URL http://server/site/documentlibrary/testdoc.docx. There is no Web named "/site/documentlibrary/testdoc.docx/_vti_bin/sites.asmx".
The clientcontext needs a website url, but I don't know which part of the url is a website, site collection, library or folder. That's something SharePoint should know.
A (brute force) workaround I can think of is to try to create a clientcontext until it doesn't give any exceptions.
Thus first try the link longest link (without filename) and traverse the urlparts:
http://server/site/documentlibrary (<-- exception because it is a document library)
http://server/site (<-- bingo, this is a website)
This should also work for more complicated url's, like:
http://server/sites/site1/subsite/doclib/folder1/folder2 (exception, because it is a folder)
http://server/sites/site1/subsite/doclib/folder1 (exception, because it is a folder)
http://server/sites/site1/subsite/doclib (exception, because it is a document libarary)
http://server/sites/site1/subsite (bingo, its a subsite within a site collection which is placed in a managed path 'sites' with wildcard inclusion)
Now we have the website url and can create the clientcontext and the server relative url.
Is there a more elegant/efficient way to get the job done?