DevLost

A developer lost in the mountains

Discover Sharepoint with Silverlight - Part 2

This article is available also on SilverlightShow:
http://www.silverlightshow.net/items/Discover-Sharepoint-with-Silverlight-Part-2.aspx

In the previous part of this series we have investigated on how the Silverlight Object Model works behind the scenes. We have seen that it replicates more or less the same structure of the Server Object Model. We have also understood that we must call both Load(…) and ExecuteQueryAsync(…) methods before accessing the value properties of the client objects. Furthermore, sniffing the web traffic we have also seen that these actions are simply transformed into a WebRequest which is launched using the default credentials. We have learned that we can make even synchronous calls using ExecuteQuery(…) instead of ExecuteQueryasync(…) in a secondary thread. Eventually, I anticipated my idea to build a Silverlight application capable of surfing the object hierarchy of a Sharepoint site. Now it’s time to see it in action. Here you can watch a video showing how you can use it. Here you can download the source code.

 

A simple “Sharepoint navigator” application

If you look around you may find some great open source projects that allow you to get tons of information from a Sharepoint installation. For instance, there is the Sharepoint Manager which is not only an impressive Sharepoint browser but also a very useful editor. There is also the Sharepoint 2010 explorer, a remarkable Winform app using the Managed Client Object Model. So I wondered: why not creating something similar in Silverlight? This is a good opportunity to see how far we can go with Silverlight and at the same time a way to study the object model of Sharepoint.

In the image below you can see a screenshot of the application:

screenshotapp

I want to say in advance that this application has to be considered as an experiment and it is not in any way comparable with the above mentioned projects in terms of functionalities. However, I think it is a good starting point if someone wishes to improve it in order to create a nice tool. On the left side there is a treeview containing a hierarchy of Sharepoint objects starting from the root object i.e. the “Site” object. On the main central area, on top, there is the type of the object selected in the treeview, and below there is the DataGrid containing all the readable properties of the selected object while in the window in blue there is the query used to obtain the property types and values of the object selected.

How to use the application

The Visual Studio solution of the application (downloadable here) contains 2 projects; the first is the Silverlight project itself and the other one is the project of the Sharepoint Visual Web Part which hosts the Silverlight application. All you have to do is build and deploy the web part (called “SP_SL_NavigatorVWP”) to your Sharepoint site and then insert it in a page. The mechanism is the same as I described in one of my previous articles. Just look here at the paragraph “Deploy the Silverlight application using a Visual WebPart” for all the details. Once the application has been started it shows just one item on the treeview, i.e. the “Site” object as in the picture below:

SiteScreenshot

From here you can explore the objects hierarchy in two ways (or using a combination of the two ways):

1) Using a pre-packaged query

2) Using a hand-packed query

One right click on the “Site” item shows the following Context Menu with the two options:

ContextMenu1

Remember what we said in the introduction: before accessing the value properties of the client objects you have to load a query and launch the request to Sharepoint. Programmatically speaking it means that you should provide a lambda expression to the Load method of the Client Context object describing the data you want to know . To explain it better let me recall an example from one of my previous articles :

 myClContext = new ClientContext("http://My_Server_name");
 myClContext.Load(myClContext.Web.Lists);
 myClContext.ExecuteQueryAsync(OnConnectSucceeded, OnConnectFailed);

In the code above we want to know more about the Web object and its Lists. Looking at the definition of the Load(…) method:

 public void Load<T>(
     T clientObject,
     params Expression<Func<T, Object>>[] retrievals
 )
 where T : ClientObject

We could rewrite the example above using a lambda expression in the following way:

 myClContext = new ClientContext("http://My_Server_name");
 myClContext.Load(myClContext.Web, item => item.Lists);
 myClContext.ExecuteQueryAsync(OnConnectSucceeded, OnConnectFailed);

With the “pre-packaged query” option a lambda expression is automatically created using all the available properties of the client object selected; we will come back on this later. With the “hand-packed query” we have to build the expression by hand.

The “hand packed query” option

Once you have clicked on the “hand packed query” option you will see the basic editor below:

handQuery

In the black TextBox you can insert a lambda expression asking for information related to the Client object selected in the treeview. Since it is a very rudimental tool do not blame it on me if your gorgeous and complicated query will not be recognized J. See it as an exercise to understand the object model of Sharepoint. For instance, in the image above we see that the “Site” object has some properties; one is called “Features”, another one “RootWeb” and so on. What if we want to know more about these properties? Just write the query as I did and click OK.

The “pre-packaged query” option

With this option the query is pre-packaged for you. It is done by collecting all the properties available to the client object selected, creating a lambda expression for each of them, storing all these expressions in an array and passing the array to the Load(…) method. The application provides a “query details” inspector which allows you to see the query just executed as in the blue box of the picture below:

QueryDetails

In detail, the underlying mechanism responsible for packaging the query performs the following actions:

1) it uses Reflection to create a MethodInfo instance representing the Load(…) method of the client object as in the code snippet below:

 public static MethodInfo GetLoadMethod(ClientContext cliContext, ClientObject cliObject)
 {
  
     MethodInfo miLoad = cliContext.GetType().GetMethod("Load", BindingFlags.Instance | BindingFlags.Public);
     
     miLoad = miLoad.MakeGenericMethod(cliObject.GetType());
     
     return miLoad;
  
 }

2) it gets all the readable properties of the client object as in the code snippet below:

 var clientProps = locCLientObject.GetType(
     .GetProperties(BindingFlags.Public | BindingFlags.Instance)
     .Select(p => p)
     .Where(p => propsToSkip.Contains(p.Name) == false);

3) it builds a lambda expression for each property as in the code snippet below:

 public static Linq_Expression GetLambdaForLoadMethod(ClientObject cliObject, PropertyInfo prop)
 {
     Type cliType = cliObject.GetType();
     Linq_Expression exp = null;
     
     try
     {
         // we want to build an expression like: Expression<Func<T, object>>
         
         // 1. builds the delegate type
         Type delegType = typeof(Func<,>).MakeGenericType(cliType, typeof(object));
          
         // 2. builds the parameters of the expression
         ParameterExpression parmsExp = Linq_Expression.Parameter(cliType, "i");
         
         // 3. builds the body expression
         MemberExpression bodyExp = Linq_Expression.Property(parmsExp, prop);
          
         // 4. converts the body expression to a type compatible with the type arguments of the delegate type
         UnaryExpression bodyExpConverted = Linq_Expression.Convert(bodyExp, typeof(object));
          
         // creates lambda expression
         exp = Linq_Expression.Lambda(delegType, bodyExpConverted, parmsExp);
          
     }
     catch { }
      
     return exp;
      
 }

4) it creates the array of lambda expressions and uses the MethodInfo instance to invoke the Load(…) method and pass the array:

 expressionsArray = Array.CreateInstance(exprType, clientProps.Count());
 int propCounter = 0;
  
 foreach (PropertyInfo prop in clientProps)
 {
     Linq_Expression lamba_exp = SL_SPUtils.GetLambdaForLoadMethod(locCLientObject, prop);
     object converted_lamba_exp = Convert.ChangeType(lamba_exp, exprType, CultureInfo.CurrentCulture);
     
     expressionsArray.SetValue(converted_lamba_exp, propCounter);
     expressionsList += lamba_exp.ToString().Replace("Convert", "") + "\r\n";
      
     propCounter += 1;
 }
   
 // invoke Load with parameters
 MethodInfo methodLoad = SL_SPUtils.GetLoadMethod(locClientContext, locCLientObject);
 try
 {
     methodLoad.Invoke(locClientContext, new object[] { locCLientObject, expressionsArray });
 }
 catch (){}

The approach is more or less the same used in the source code of the already mentioned Sharepoint 2010 explorer which inspired me in fact.

Navigate and learn Sharepoint using the application

The title of this section summarizes the final objective of this article. As we have already seen, at a first glance the application shows only a root client object called “Site” and its properties:

SiteScreenshot

No query has been made so far. This is just what we have on hand after the initialization of the ClientContext object:

 ClientContext myClientContext = new ClientContext("http://my_site”);
 Site mySite = myClientContext.Site;

This is not much but it is enough to say that the “Site” does not represent just a “Web Site” as we could imagine, but a site collection - basically a root web site with its sub-sites. In fact, if you look at the properties Grid you will find a property called “RootWeb” which contains information about the main web site and the underlying sites. You can see also other interesting properties which in some case reflect functionalities of Sharepoint. For instance, the Property “Features” is a “ClientObjectCollection”, namely a collection of client objects representing a “Feature”. What is a “Feature” in the Sharepoint world? Well, the concept behind that is not exactly what you may expect: we could define it as a single functionality packaged in order to be activated, deactivated, updated or deleted. Its scope can be at farm level or a web application level or even a site level. The various editions of Sharepoint 2010 come with a different number of built-in features; for instance, the “Team Collaboration Lists” and the “Group world Lists” area feature included in all the version of Sharepoint. They provide team collaboration capabilities like document libraries, calendars and so on. A feature is often used to customize a site; even the VS2010 project of the application of this article contains a feature:

FerryBoatFeat1

And you can activate or deactivate from the “site settings/Features” of your site:

FerryBoatFeat

Let me take a step forward now; I want to know more about the “RootWeb” property; using the “hand-packed” query option you can write something like this:

QueryRootWeb

And the result is:

QueryRootWebResults

As you can see, the RootWeb is quite a big object which represents the main site (look at the site title highlighted in red); it contains, among others, the “Webs” ClientObjectCollection. If we now create another query on this object, for instance writing the following in the editor: “item => item.Webs” we will be able to see all the subsites of our site as in the image below:

DocumentsSite

As you may notice I have just one subsite called “Documents Site” in my main site.

From here you could continue to explore the client object model either using the “hand-packed query” option or the “pre-packaged query” option to your choice, bearing in mind that the first option lets you focus on investigating one or few properties at a time, while the second option asks the server for all the properties, and it is obviously heavier.

Summary

In this article we have seen that using Silverlight we can build a small tool capable of navigating in the hierarchy of the client object model that Sharepoint 2010 puts at disposal of the Silverlight developers. We have also seen that it can be used as a kind of compute based training to learn the concepts of the Sharepoint world.

A Silverlight menu for Sharepoint




Read my articles on silverlightshow.net:

Silverlight and Sharepoint working together: a Silverlight menu for Sharepoint - Part 1

Silverlight and Sharepoint working together: a Silverlight menu for Sharepoint - Part 2

Discover Sharepoint with Silverlight - Part 1

This article is available also on SilverlightShow:
http://www.silverlightshow.net/items/Discover-Sharepoint-with-Silverlight-Part.aspx

Let me take a step back: in my first article on the winning pair (Sharepoint & Silverlight) I described how to set up a development environment and how to use three different ways to insert a Silverlight application in a Sharepoint site. In a second article I briefly highlighted how to interact with Sharepoint objects inside of a Silverlight application. Now it should be the time to go through the concepts in depth and try to better understand how we can steer Sharepoint by using the Silverlight Client Object Model. So I wondered why not creating an application that can navigate through the hierarchy of the objects exposed by Sharepoint and show its properties? And this was when the title of this article crossed my mind. Exploring, and in a certain way discovering Sharepoint using a sort of Silverlight navigator could be a good opportunity to learn something on the Sharepoint framework and, at the same time, to become familiar with the Silverlight Client Object Model.

This is exactly what we start to see in this article. In the next article we will see the application in action and it will be possible to download the source code.

 

This article may be useful to…

Silverlight developers who want to create Rich Internet Applications exploiting the potential offered by the Sharepoint 2010 platform. To achieve this they need to learn the main concepts behind that and know how to use the internal objects of Sharepoint.

 

Two words on Sharepoint 2010

There is something that I overlooked in my previous articles, indeed. I thought that from the point of view of a Silverlight developer, knowing in broad terms what is Sharepoint as well as the potential contribution of Silverlight are elements deserving a few words. SharePoint is essentially a business productivity platform built on a Web-based technology and you can interact with it using a web browser over an intranet, extranet, or Internet solution. Here is what sharepoint offers:

- An extended collaboration platform which includes enterprise content management (ECM), Web content management (WCM), business intelligence features and social capabilities (blogs, portals, tagging and so on)

- A complete interoperability platform with office applications and means to handle line of business data

- a rich development platform which ensures extensibility and customization.

Focusing on the last point, we can say that Sharepoint 2010 provides both a framework with tools and means to aid power users in building high level applications and a complex programming environment. You may work with page layouts and master pages to change the look and feel as well as the way in which the contents are structured. You can control the flow of information creating the so called workflows, namely business processes intended as sequences of steps to be performed in order to achieve a target. All these tasks can be performed using the high level tools and features offered by the environment. For developers who want more control, Sharepoint comes with a rich object model which has been totally server-based since the beginning. And for client application? Now in Sharepoint 2010 there is a client object model declined into three sub-types: for .NET managed applications, for ECMAScripts executing in the browser and for Silverlight applications. In this model most of the server objects are mapped to client objects with a similar name as in the non-exaustive table below:

tabellaClient

Explaining in detail all these objects is beyond the scope of this article but it’s obvious that a Silverlight developer who wants to seriously build Silverlight apps that strongly interact with the framework should be aware of the Server Object model.

 

The Silverlight client object model behind the scenes

I don’t want to describe the basics of the SL COM (Silverlight Client Object Model) here, since there is the official tutorial for that. But there is something else I want to highlight, that is the mechanism behind. When I was doing my first experiments a particular method of the class Clientcontext caught my attention, that is “ExecutingWebRequest”. I wrote the piece of code below to investigate it further:

 private void ContactSharepoint(string siteUrl)
 {
     myClContext = new ClientContext(siteUrl);
     myClContext.ExecutingWebRequest += new EventHandler<WebRequestEventArgs>(myClContext_ExecutingWebRequest);
     myClContext.Load(myClContext.Site);
     myClContext.ExecuteQueryAsync(OnQuerySucceeded, OnQueryFailed);
 }
  
 void myClContext_ExecutingWebRequest(object sender, WebRequestEventArgs e)
 {
     WebRequest wb = e.WebRequest;
  
 }

Here substantially I created a new ClientContext passing the Url of my Sharepoint site in order to know its properties. The logic is simple and straightforward: if you want to obtain information about properties and features regarding one or more properties of one or more client objects you have to use the ClientContext as main entry point, “load” it in your request (the “Site” object in the example above)and fire the query. I added an event handler for ExecutingWebRequest and I put a breakpoint inside the handler as in the image below:

FirstRequest

In this way I discovered that the ExecuteQueryAsync(…) method performs a first HttpWebRequest to the Site Web service (http://<server-url>/_vti_bin/sites.asmx) and then a second HttpWebRequest to the Client Web Service (http://<server-url>/_vti_bin/client.svc) as in the image below:

SecondRequest

The first request is performed only once when Sharepoint is contacted for the first time, all the subsequent requests are turned to the Client web service. So, what happens next? To understand it better I used the Fiddler tool in order to capture and analyze the web traffic.

The image below shows the details captured by Fiddler:

FirstFiddler

In the text area on the top right panel you can see the request invoking the method GetUpdatedFormDigest of the Site web service, and in the text area below the response. This method returns a security validation value (a FormDigest value). What is its purpose? This link http://msdn.microsoft.com/en-us/library/ms472879.aspx clarifies it all. It claims that a web application cannot “modify the contents of the database unless you include security validation on the page making the request.” And furthermore “When the user requests a page, the server returns the page with security validation inserted. When the user then submits the form, the server verifies that the security validation has not changed.” Practically this first request is made to obtain a token with an expiration time which is used by Sharepoint to verify that the subsequent requests to the Client Web Service are genuine. Let’s analyze the second request now. The traffic captured is:

SecondFiddler

In the response we see clearly that we requested information about an object of type SP.Site and all its properties. We also notice another thing: the request is formatted in XML and the response, instead, is in JSON format. Why this? Most probably because the “client.svc” web service is used also by the ECMAScript Object Model to allow javascript developers to use a similar object -oriented pattern. What is important is that for a “client developer” (i.e. Silverlight, javascript or even .managed apps developer) the mechanism is transparent:

1) the Client Object Model translates the request in xml and passes it to the client.svc

2) The client.svc interrogates the content database and returns the response in a JSON format

3) the Client Object Model finally maps the JSON objects to the relevant client objects

now , what if we want to know more about the object Web and, in particular, its title as in the code below?

 private void ContactSharepoint(string siteUrl)
 {
     myClContext = new ClientContext(siteUrl);
     myClContext.ExecutingWebRequest += new EventHandler<WebRequestEventArgs>(myClContext_ExecutingWebRequest);
     myClContext.Load(myClContext.Web, w => w.Title);
     myClContext.ExecuteQueryAsync(OnQuerySucceeded, OnQueryFailed);
 }
  
 void myClContext_ExecutingWebRequest(object sender, WebRequestEventArgs e)
 {
     WebRequest wb = e.WebRequest;

 Once again the web traffic captured reveals some interesting things:

ThirdFiddler

The request passes the Digest value previously obtained to ensure that it is valid and the list of actions required with the query linked. In the response we are informed that the value of the title property of the object SP.Web is “Team Site”. This introduces another interesting argument, that is how the parameters are passed to the Load(…) and LoadQuery(…) methods of the ClientContext object and this is the object of the next paragraph.

 

Asking information to Sharepoint: Load(…) and LoadQuery(…)

The Load(…) and LoadQuery(…) methods of the ClientContext obect are defined as follows:

 public void Load<T>(T clientObject, params Expression<Func<T, object>>[] retrievals) where T : ClientObject;
  
 public IEnumerable<T> LoadQuery<T>(ClientObjectCollection<T> clientObjects) where T : ClientObject;
 public IEnumerable<T> LoadQuery<T>(IQueryable<T> clientObjects) where T : ClientObject;

We have already seen some simple examples of using the Load(…) method in this and in my previous article.

At this point it should be clear that when using these methods, the underlying Client Object Model engine prepares a request to Sharepoint in order to know the values of the objects passed as an argument. The request is fired only when we call the ExecuteQueryAsync(…) or the ExecuteQuery() methods of the CleintContext and you can inspect and use the Client objects requested only after this call.

I want to focus on the second argument now. It is (in case of Load(…) method) an array of Lambda Expression with reference to objects of type “ClientObject”. The ClientObject class is the base class for all the client objects listed in the “server-client objects correspondence table” above. So what? Let’s think of an application where starting from a root node you want to know information on all the child nodes as in a treeview – logic and let’s imagine that each node represents a ClientObject of Sharepoint with its properties (petals). In this way you could start from the root node, i.e. the Site object and get all the child nodes with subsequent requests to Sharepoint. Virtually you could navigate each branch of the tree preparing each time the correct expression to pass to the Load(…) method. The question is: how to generalize this via code? One way is to use reflection and in the second part of this article we will see how.

 

ExecuteQueryAsync(…) VS ExecuteQuery(…)

In my previous article I told you that “ […] since Silverlight follows an asynchronous model, you can only make asynchronous queries to the Sharepoint Server from the UI thread. You can perform synchronous queries only in a thread that does not interact with the UI thread […] “.

On the basis of this statement it should be possible to make synchronous queries using ExecuteQuery() also in Silverlight with some caution. In my application I put the call in a secondary thread and I verified that it works. The implementation is very simple, in the code below I instantiated a Thread object passing a lambda expression as argument and then I started the thread. In this way the ExecuteInThread(…) method is executed in a secondary thread and can be used to call ExecuteQuery(…).

 public void ExecuteAction()
 {
  
     Thread t = new Thread(() => ExecuteInThread(new
                                            {
                                                ClientContext = m_clientContext,
                                                ClientObject = m_clientObject,
                                                LeftTreeItem = m_currentItem
                                           }
                                           ));
     
     
     t.Start();

In conclusion using either ExecuteQueryAsync(…) or ExecuteQuery(…) is your choice depending on the scenario.

 

The Silverlight Client Object Model and OOB application limitations

During my experiments I discovered one inconvenience. If you want to use the SL Client Object Model in a SL OOB application, keep in mind that there are strong limitations. The fact is that inside an OOB (Out Of Browser) application from the point of view of Sharepoint you are impersonating an anonymous user and you can view and do just what the anonymous user can view and do. This depends on the fact that the SL Client Object Model interacts with Sharepoint using the default credentials as you can see in the image below where I put a breakpoint on the ExecutingWebRequest() event handler:

DefaultCredentials

With the managed client model (that is the model used for managed applications like command-line apps, winforms and WPF applications) you can change the authentication mode on the ClientContext object using the AuthenticationMode property. For instance, you can set this property on forms authentication which gives you the possibility to supply username and password (obviously you have to enable forms authentication in your Sharepoint site in this case). Unfortunately in the Silverlight client object model this property is not implemented and this means that if you want to interact with Sharepoint using an OOB application you have to take care of all the details needed to perform the authentication.

 

Summary

In this article we began exploring Sharepoint using Silverlight. We have looked more closely at the Silverlight Object Model and we have discovered how it works behind the scenes. We have also given a look to server and client object hierarchy of Sharepoint and highlighted the limitations in terms of interaction between the SL client object model and SL OOB applications. In the second part of the article we will see a SL application able to navigate the hierarchy of client objects and to show their properties.