Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to detect if a ClientObject property is already retrieved/initialized

If you're using the Client Object Model from SharePoint and access properties which haven't been initialized or already retrieved by an

Context.Load(property); 
Context.ExecuteQuery();

you get for example a:

Microsoft.SharePoint.Client.PropertyOrFieldNotInitializedException

or

The collection has not been initialized. It has not been requests or the request has not been executed.

Exception.

Is there any proper way to check before accessing these properties if they are already initialized/retrieved? Without a Try/Catch approach. I don`t like that one's.

I want to check before a Exception has been thrown and handle it.

I already checked the

IsObjectPropertyInstantiated

IsPropertyAvailable

Methods but they don't help really. IsPropertyAvaiable only checks scalar properties and won't give a result on for example Web.Lists and IsObjectPropertyInstantiated returns true for Web.Lists although Web.Lists was not initialized.

like image 986
Mark Avatar asked Sep 05 '14 06:09

Mark


2 Answers

I would say your question is already contains the correct answer to some extent.

In order to determine whether client object property is loaded or not the following methods are available:

  • ClientObject.IsPropertyAvailable method method indicates whether the specified scalar property has been retrieved or set
  • ClientObject.IsObjectPropertyInstantiated method indicates whether the specified property of the client object is instantiated

Tests

Test case 1: load scalar property only

ctx.Load(ctx.Web, w => w.Title);
ctx.ExecuteQuery();
//Results:
ctx.Web.IsObjectPropertyInstantiated("Lists")  False
ctx.Web.IsPropertyAvailable("Title")    True

Test case 2: load composite property only

ctx.Load(ctx.Web, w => w.Lists);
ctx.ExecuteQuery();
//Results:
ctx.Web.IsObjectPropertyInstantiated("Lists")  True
ctx.Web.IsPropertyAvailable("Title")    False

Test case 3: load both scalar and composite properties

ctx.Load(ctx.Web, w=>w.Lists,w=>w.Title);
ctx.ExecuteQuery();
//Results
ctx.Web.IsObjectPropertyInstantiated("Lists")  True
ctx.Web.IsPropertyAvailable("Title")    True


How to dynamically determine whether client object property is loaded or not?

Since ClientObject.IsPropertyAvailable and ClientObject.IsObjectPropertyInstantiated methods expect the property name to be specified as a string value and that could lead to typos, I usually prefer the following extension method:

public static class ClientObjectExtensions
{
    /// <summary>
    /// Determines whether Client Object property is loaded
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="clientObject"></param>
    /// <param name="property"></param>
    /// <returns></returns>
    public static bool IsPropertyAvailableOrInstantiated<T>(this T clientObject, Expression<Func<T, object>> property)
        where T : ClientObject
    {
        var expression = (MemberExpression)property.Body;
        var propName = expression.Member.Name;
        var isCollection = typeof(ClientObjectCollection).IsAssignableFrom(property.Body.Type);
        return isCollection ? clientObject.IsObjectPropertyInstantiated(propName) : clientObject.IsPropertyAvailable(propName);
    }
}

Usage

using (var ctx = new ClientContext(webUri))
{

     ctx.Load(ctx.Web, w => w.Lists, w => w.Title);
     ctx.ExecuteQuery();


     if (ctx.Web.IsPropertyAvailableOrInstantiated(w => w.Title))
     {
         //...
     }

     if (ctx.Web.IsPropertyAvailableOrInstantiated(w => w.Lists))
     {
         //...
     }
} 
like image 63
Vadim Gremyachev Avatar answered Oct 27 '22 14:10

Vadim Gremyachev


The tests provided by Vadim Gremyachev only cover one half of the scenarios - where you use ctx.Load. But when you use ctx.LoadQuery the result changes:

var query = from lst in ctx.Web.Lists where lst.Title == "SomeList" select lst;
var lists = ctx.LoadQuery(query);
ctx.ExecuteQuery();
ctx.Web.IsObjectPropertyInstantiated("Lists") -> True
ctx.Web.Lists.ServerObjectIsNull -> False
ctx.Web.Lists.Count -> CollectionNotInitializedException

So once the LoadQuery has been called on a collection, you can no longer see if the collection is actually available.

Only way in this case is to detect that the exception occurs.

like image 1
Thomas Jørgensen Avatar answered Oct 27 '22 13:10

Thomas Jørgensen