Quantcast
Channel: Second Life of a Hungarian SharePoint Geek
Viewing all articles
Browse latest Browse all 206

Strange (?) Behavior of the Client Object Model You should be Aware of

$
0
0

Note: The code examples in this post are based on the managed client OM (C#), however, you can expect the same behavior when working with the JavaScript / Silverlight versions of the client OM, both for SharePoint 2010 and 2013, furthermore, the behavior I describe applies to the client OM of Project Server 2013 as well.

Assume you have a SharePoint list including two fields, Title is a text column, and User is a field of type People or Group. You would like to update both of these fields via the client object model.

In the first case we simply set fix values for the item with Id=1, the text ‘Test’ for Title and an integer (2) as user Id for the User field.

using (var context = new ClientContext(webUrl))
{
  var web = context.Web;
  var list = web.Lists.GetByTitle("TestList");

  var item = list.GetItemById(1);
  item["Title"] = "Test";

  var userValue = new FieldUserValue();
  userValue.LookupId = 2;
  item["User"] = userValue;

  item.Update();
 
  context.ExecuteQuery();
}

Everything works as expected, both of the fields are updated by the query.

In the second case, we would like to set the same values for the item with Id=2, but in this case we get the user Id from the Id of the current user (that has “accidentally” the value 2 in this case). To get that value, we call the ExecuteQuery in the middle of the code, after setting the Title field, and before setting the User field and before invoking the Update method on the item. Finally we invoke the ExecuteQuery method again.

using (var context = new ClientContext(webUrl))
{
  var web = context.Web;
  var list = web.Lists.GetByTitle("TestList");

  var item = list.GetItemById(2);
  item["Title"] = "Test";

  var userValue = new FieldUserValue();
  var cu = web.CurrentUser;
  context.Load(cu, u => u.Id);
  context.ExecuteQuery();

  userValue.LookupId = cu.Id;
  item["User"] = userValue;

  item.Update();
 
  context.ExecuteQuery();
}

One could expect that both of the fields would be updated, however, the Title field won’t be in fact, and we will understand why, after having a look at the requests (for example, using Fiddler) sent by the client OM.

In the first case, there is a single request that includes setting both of the fields (see the SetFieldValue methods in the screenshot below, one for each field) and invoking the Update method.

image

In the second case there are two requests sent by the client OM, one for each in ExecuteQuery code.

The first request includes a single SetFieldValue method for the Title field, the query for the Id of the current user is not included in the screenshot for the sake of simplicity:

image

The second request includes a single SetFieldValue method for the User field, and invoking the Update method.

image

You can see, that calling ExecuteQuery for the the Id of the current user submits the change of the Title field as well, and thereby clears the “dirty” flag of the field (that means it won’t be re-submitted by the OM once again in later requests), but due to the lack of invoking the Update method in this request, this value change has no effect, it is simply not persisted. In the second query we call the Update method, but in this request only the change in the User field was submitted, it has no effect on the Title field.

Lesson learned: The requests sent by the client OM are independent on the server side, no session state or context is persisted between the requests. Only data changed since the last request or required to be able to perform the current request on the server side are sent by the client OM. You should consider the code blocks between (or before) calling ExecuteQuery as they were separate server side console applications you try to run one after another. In this case you won’t expect either, that setting a field without calling the Update method may have any effect on the persisted value of the field. If you are aware of the client OM architecture internals, this is just the expected behavior. If you are not, you might have such surprises in the future.



Viewing all articles
Browse latest Browse all 206

Trending Articles