The Microsoft Client Object Model (CSOM) has three different platform libraries, one for managed code, one for Silverlight and another ECMA script based library. The client object models are provided through a proxy (.js files ECMA script) and (assembly files managed and Silverlight), which can be referenced in custom applications like other object models. The object models are implemented as a Windows Communication Foundation (WCF) service (.../_vti_bin/client.svc), but uses Web bindings to implement efficient request batching. All operations are inherently asynchronous, and commands are serialized into XML and sent to the server in a single HTTP request. The Silverlight and ECMA models require you to execute your code on a separate thread. This prevents CSOM calls locking the UI thread and making the UI unresponsive. In my opinion executing potential long running processes on a separate thread is the best approach for responsive applications. However, many developers find asynchronous programming confusing and messy. This type of programming requires callback methods to handle success and failure, thus making the flow of the code disjointed. The CSOM makes this easy for developers by providing the ClientContenxt.ExecuteQueryAsync method. This method enables you to use the Sivlerlight/ECMA object model the same way you would using the managed object model except when sending the request to the server the developer must provide a callback methods.
The two approaches to CSOM Silverlight asynchronous programming
A standard approach is to define callback methods in your class to handle the response of the ExecuteQueryAsync method. The example below shows how to look up a user using a CAML query to the user information list. The example uses two defined methods, one for success and one for failure. The success method handles getting data back from the call. There are a couple of problems with this approach. One is that you must declare and store the return data in a class level variable and second you can not re-use the Success method because it has become tightly coupled with the class level ListItemCollection varable named users. This approach would require you to create a class level variable for every type of return object and a success callback for each ExecuteQueryAsync call. Keeping track of which methods use which call backs can become very confusing.
public void LookupUser1() CamlQuery camlQuery = new CamlQuery(); this.users = clientContext.Web.SiteUserInfoList.GetItems(camlQuery); clientContext.ExecuteQueryAsync(Success, Failure); } } private void Success(Object sender, ClientRequestSucceededEventArgs args) private static void Failure(Object sender, ClientRequestFailedEventArgs args) |
The second approach is to use Anonymous methods in place of defined call back functions. Anonymous methods were introduced in C# 2.0 and the ability to use multi-line and lambda expressions was introduced in C# 3.0. http://msdn.microsoft.com/en-us/library/0yw3tz5k(v=vs.100).aspx You can use these in VB.net but they do not support multi-line and lambda expressions. The example below is the same code in the first example but now is using anonymous methods to process the return values. Anonymous methods have the ability to read and write to variables declared in the local method, so there is no need to declare them at the class level. Secondly, the code flows and remains contextually together and coherent.
public static void LookupUser2() ListItemCollection users = clientContext.Web.SiteUserInfoList.GetItems(camlQuery); clientContext.ExecuteQueryAsync((object eventSender, ClientRequestSucceededEventArgs args1) => }, (object sender, ClientRequestFailedEventArgs eventArgs) => } } |
Uploading a document and setting metadata
Some tasks in SharePoint require multiple steps and programming them with the Sivlerlight object model becomes difficult. One task would be uploading a document to a folder or document set and setting the metadata. How difficult could that be? Well this requires 4 separate steps and 4 ExecuteQueryAsync calls.
- Get the folder or document set
- Upload the file
- Set the metadata
- Update the list item
The following example shows how this can be done using anonymous methods so the task can be completed in one method block. Please note this code is not production level code since you will have to fill code for getting the byte array of the document.
public static void UploadFile(string siteUrl, ClientContext context = new ClientContext(siteUrl); Folder docSetFolder = web.GetFolderByServerRelativeUrl(listName + "/" + targetFolder); //STEP 1 GET FOLDER/DOCUMENTSET FileCollection documentFiles = docSetFolder.Files; //STEP 2 ADD DOCUMENT context.Load(newFile); //STEP 3 SET METADATA //start setting metadata here //STEP 4 UPDATE ITEM string ret; }, (object eventSender4, ClientRequestFailedEventArgs eventArgs4) => }, (object eventSender3, ClientRequestFailedEventArgs eventArgs3) => }, (object eventSender2, ClientRequestFailedEventArgs eventArgs2) => }, (object eventSender, ClientRequestFailedEventArgs eventArgs) => |
Awaiting the future of asynchronous programming in Silverlight
There is no need to pull your hair out doing asynchronous programming. You can even do anonymous methods in jscript and use them with the ECMA CSOM. Anonymous methods allow you to put the code where it needs to be. The future of asynchronous programming in Silverlight can be seen now in Silverlight 5 and the System.Threading.Tasks namespace. This namespace is particularly useful with the HttpWebRequest methods that support the IAsyncResult interface. The example below shows how to use the Task.Factory to download a file and handle the response in one code block. http://msdn.microsoft.com/en-us/library/dd537609.aspx
string uri = "http://basesmc2008/lists/tester.xml"; |
We also await future changes to the SharePoint client object model and the possibility of using the new .Net 4.5 feature of “Async await” which hopefully will be in the next version of Silverlight. http://blogs.msdn.com/b/dotnet/archive/2012/04/03/async-in-4-5-worth-the-await.aspx
1 comment:
Hi,
Thanks for posting a good article, It works fine if I am calling it once, but if I am trying to call it for multiple time i.e. inside a loop, it works for only once(Adding only one file)
Can you please highlight if is there way to call it inside loop.
Post a Comment