Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

In SharePoint 2013 CSOM is it better to pass a Context object around, or a Url to open a context?

Which would be the best example: (Please consider there may be a lot of methods preforming tasks)

1) Pass Context, open Web

EnableSomethingOnWeb(ClientContext ctx, bool enable){
   ctx.Load(ctx.Web);
   // enable something
   ctx.ExecuteQuery();
}

var ctx = new ClientContext("http://myweb");
EnableSomethingOnWeb(ctx, true);

2) Pass Url, open ClientContext, Open web

EnableSomethingOnWeb(string Url, bool enable){
   var ctx = new ClientContext(Url);
   ctx.Load(ctx.Web);
   // enable something
   ctx.ExecuteQuery();
}

EnableSomethingOnWeb(webUrl, true);

3) Pass Web, Execute ClientContext

EnableSomethingOnWeb(Web web, bool enable){

   // enable something
   web.Context.ExecuteQuery();
}

var ctx = new ClientContext("http://myweb");
ctx.Load(ctx.Web);

EnableSomethingOnWeb(ctx.Web, true);
*keep in mind following calls may continue pass this web object around.
share|improve this question

2 Answers 2

up vote 4 down vote accepted

Do:

  • Pass around ClientContext.
  • Call .ExecuteQuery() as few times as possible, bundle/batch up with .Load().
    • Once is usually enough, only in a very few cases do you need more.

Do not:

  • Do not pass around Web.
    • You need to reference other members from ClientContext, such as Site.
  • Do not pass around an URL (either as String or Uri).
    • Initialization method of ClientContext can alternate, e.g., provider hosted apps use this: SharePointContextProvider.Current.GetSharePointContext(HttpContext).CreateUserC‌​lientContextForSPHost().

Also:
I usually make "Repository" classes, which work on ClientContext without actually calling .ExecuteQuery(), so I bundle up (batch) .Load commands and fire them on the "outside", then come back to the Repository.

public class ListAndViewRepository
{
    private readonly ListCollection _lists;
    public List<List> Lists { get; set; }
    public List<View> Views { get; set; }

    public ListAndViewRepository(ClientContext clientContext)
    {
        _lists = clientContext.Web.Lists;
        clientContext.Load(_lists,
            collection =>
                collection.Include(l => l.Id, l => l.Title,
                    l => l.Views.Include(v => v.Id, v => v.Title, v => v.ViewFields, v => v.ViewQuery)));
    }

    public void Execute()
    {
        Lists = _lists.ToList();
        Views = Lists.SelectMany(list => list.Views.ToList()).ToList();
    }
}

Used something like this:

var listAndViewRepository = new ListAndViewRepository(clientContext);
// ... do a lot of other "repositories"
clientContext.ExecuteQuery();
// ... call "Execute" on other "repositories"
listAndViewRepository .Execute();
var lists = listAndViewRepository.Lists;
var views = listAndViewRepository.Views; 
share|improve this answer
    
So to clarify, constructing class libraries should use "ClientContext" because of multiple ways to init the object may cause inconsistencies? –  Elliot Wood Apr 14 at 5:51
1  
@ElliotWood: Yes, they should not initialize the object. In provider hosted apps you do something like SharePointContextProvider.Current.GetSharePointContext(HttpContext).CreateUserC‌​lientContextForSPHost() instead of just new ClientContext. –  eirikb Apr 14 at 5:53

Objects like Web, ClientContext are passed by reference, that is they are not copied. So there is no need to worry about performance. However, as mentioned by @eirikb, pasing ClientContext between methods make more sense as you can then load whatever objects you want from it inside the method.

share|improve this answer
    
Note that when you initializing a new instance of ClientContext it will validate the URL, so at least 10 nanoseconds to save there. Although when initializing in a provider hosted app the overhead is much much larger –  eirikb Apr 14 at 5:44
    
@eirikb, so it is good to initialize ClientContext once and then pass between methods rather than passing url and initializing inside the method. –  Nadeem Yousuf Apr 14 at 5:54
    
@Nadeem So by ref would imply you could get the context and call other things by going: var ctx = web.Context; ctx.Load(...)?? –  Elliot Wood Apr 14 at 5:56
    
@ElliotWood, That is right. However, if ClientContext is passed instead of Web then there is no need to do var ctx = web.Context –  Nadeem Yousuf Apr 14 at 6:05

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.