39

SharePoint 2013 CSOM API contains the following methods for accessing List object:

For example:

var listTitle = "Tasks";
using(var ctx = new ClientContext(webUrl))
{
     var list = ctx.Web.Lists.GetByTitle(listTitle);
     ctx.Load(list);
     ctx.ExecuteQuery();
}

From another hand, SSOM API contains SPWeb.GetList method to gets the list that is associated with the specified server-relative URL.

The question is: how to effectively load List by server-relative URL in CSOM?

Vadim Gremyachev
  • 42,498
  • 3
  • 86
  • 167
  • 1
    Vadim, if you had mention using another method other than CSOM, then yes. The SOAP services has it a method that you can use - SiteData.GetURLSegments. I wrote about it here: http://paultavares.wordpress.com/2014/02/18/how-to-get-information-about-a-sharepoint-list-item-using-its-url/ – Paul T. Sep 30 '14 at 19:19
  • ListCollection lists = context.Web.Lists; context.Load(lists, all => all.Include(l => l.RootFolder)); It does not work either! – ananda May 27 '17 at 08:05

5 Answers5

33

For those who are still looking for the answer. SharePoint 2013 (since SP1 at least see UPD below) contains special method Web.GetList. It accepts site-relative url for the list, i.e. site/dev/lists/mylist.

Sample code for .NET object model:

var ctx = new ClientContext("http://sp2013dev/sites/dev");
var list = ctx.Web.GetList("sites/dev/lists/Addresses");
ctx.Load(list);
ctx.ExecuteQuery();    
Console.WriteLine(list.Title);

The same situation for JavaScript object model (except the fact that msdn documentation is lacking and you don't find this method here at the moment of writing this, May 2015):

var context = SP.ClientContext.get_current();
var list = context.get_web().getList("/sites/dev/Lists/Addresses"); 
context.load(list);
context.executeQueryAsync(function() { 
    alert("loaded!"); 
    }, function() { 
    alert("failed!"); 
});

Now we don't need all this hacks with folder or list properties.

UPD:

Just tested that this method is not included in SP1. It works starting from February 2015 CU (sorry, can't check the exact CU number)

Sergei Sergeev
  • 11,618
  • 5
  • 32
  • 49
  • Oh, finally, i suppose it should be considered as the most accurate answer then.Thanks! – Vadim Gremyachev May 06 '15 at 13:05
  • I couldn't find this method in the latest NuGet download of the DLL. Instead, I found an version of the DLL on my dev server (patched to March 2015 CU) but it didn't work for Production which is only SP1. – PeterX May 14 '15 at 04:51
  • @PeterX, you're correct, unfortunately SP1 doesn't contain this method, I've already mentioned it. It seems it was included at the end of 2014 or at the beginning of 2015. – Sergei Sergeev May 14 '15 at 08:37
  • I can confirm that it also works with absolute urls – Kirschi Aug 10 '16 at 08:32
  • 3
    And as it's included in the CSOM, now the REST endpoint are also updated: _api/web/getList('/sites/yoursite/yourlibraryOrList') – dbardakov Jan 26 '17 at 12:12
30

This seems to be pretty close in performance:

context.Load(lists, all => all
  .Where(l => l.RootFolder.Name == "MyListUrl")
  .Include(l => l.Id));
context.ExecuteQuery();
list = lists.Single();

If you need to get this by server-relative url you would need to parse the web url and list url first.

thomius
  • 2,808
  • 8
  • 35
  • 50
  • 1
    Had to take some performance tests away from the answer because of high variance. Anyways there doesn't seem to be big difference in performance (~0-25%). – thomius Sep 30 '14 at 13:16
  • 1
    Cool, also added an extension method here: Not so pretty with all the parsing.. – thomius Sep 30 '14 at 15:03
  • Took the extension method away because didn't invent how to protect against user giving a subfolder as an argument (instead of the actual list/library RootfolderName), without executing query more than once. – thomius Sep 30 '14 at 15:38
19

Yet another version to load List by server relative Url using CSOM.

The solution consists of the following steps:

  1. Retrieve list Folder object using Web.GetFolderByServerRelativeUrl method
  2. Retrieve List by specifying List ID stored in vti_listname property from Folder.Properties object

Code:

static class WebExtensions
{
    /// <summary>
    /// Load List by server relative Url
    /// </summary>
    /// <param name="web"></param>
    /// <param name="listUrl"></param>
    /// <returns></returns>
    public static List LoadListByUrl(this Web web, string listUrl)
    {
        var ctx = web.Context;
        var listFolder = web.GetFolderByServerRelativeUrl(listUrl);
        ctx.Load(listFolder.Properties);
        ctx.ExecuteQuery();
        var listId = new Guid(listFolder.Properties["vti_listname"].ToString());
        var list = web.Lists.GetById(listId);
        ctx.Load(list);
        ctx.ExecuteQuery();
        return list;
    }
}

Usage

using(var ctx = new ClientContext(webUrl))
{
    ctx.Credentials = new SharePointOnlineCredentials(userName,securePassword);
    var tasksList = ctx.Web.LoadListByUrl("Lists/Tasks");
    Console.WriteLine(tasksList.Title);
}

Cons:

  1. Only SharePoint 2013 CSOM is supported
  2. Requires two separate requests to server
Vadim Gremyachev
  • 42,498
  • 3
  • 86
  • 167
  • 1
    Nice usage of out-of-the-box methods, and no need to parse server-relative url. – thomius Sep 30 '14 at 15:06
  • 1
    Also you can use rest api to get list id instead of relying on property bags: http://sharepoint/_api/web/lists/?$expand=RootFolder&$filter=RootFolder/ServerRelativeUrl eq '/Lists/MyCoolList'&$select=ID. It also should reduce client-server traffic – Sergei Sergeev Mar 19 '15 at 10:55
  • I get the error Error 2 'Microsoft.SharePoint.Client.Folder' does not contain a definition for 'Properties' and no extension method 'Properties' accepting a first argument of type 'Microsoft.SharePoint.Client.Folder' could be found (are you missing a using directive or an assembly reference?) any thoughts? – PeterX May 14 '15 at 04:06
  • I had an out-of-date Microsoft.SharePoint.Client DLL. I couldn't find any MS downloads and the NuGet installer seemed to have a bug, so I harvested the DLLs from the NuGet download and added the references manually. – PeterX May 14 '15 at 04:30
  • 1
    I now get a ServerException / File Not Found. error, using either an absolute URL or a relative URL. – PeterX May 14 '15 at 04:36
  • 1
    @PeterX, if you have site/test url for site collection, then you rest query should be: http://sharepoint/sites/test/_api/web/lists/?$expand=RootFolder&$filter=RootFolder/ServerRelativeUrl eq '/sites/test/Lists/TestList'&$select=ID. Just copy paste it into the browser (with valid sharepoint and list urls) and will see the result. – Sergei Sergeev May 14 '15 at 08:34
2

I unfortunately couldn't get any of the above working, so I used an ugly hack:

public static List GetListByUrl(ClientContext context, string listUrl)
        {
            List result = null;

            ListCollection lists = context.Web.Lists;
            context.Load(lists, all => all.Include(l => l.RootFolder));            
            context.ExecuteQuery();

            string listUrlPartial = new Uri(listUrl).PathAndQuery.ToLower().Replace("%20", " ");
            foreach (List list in lists)
            {
                string thisListUrlPartial = list.RootFolder.ServerRelativeUrl.ToLower().Replace("%20", " ");
                if (listUrlPartial.StartsWith(thisListUrlPartial))
                {
                    result = list;
                    break;
                }
            }

            return result;
        }

Of course, your mileage will vary. Recommend upgrading to latest SharePoint patch to get the new method (as per @Kai's answer), but unfortunately I don't have that option at the moment.

PeterX
  • 1,020
  • 2
  • 18
  • 41
0

I do not have SP1 for my SharePoint, but this worked for me:

var clientContext = new SP.ClientContext("absolute url to sites that contains the list");

var IssueList = clientContext.get_web().get_lists().getByTitle("title of the list");