protected ConditionalScope UpdateIfChanged(Expression <Func <bool> > comparison, Action assignment) { ConditionalScope scope = new ConditionalScope(this.ClientContext, comparison, allowAllActions: true); using (scope.StartScope()) { using (scope.StartIfTrue()) { assignment(); } } return(scope); }
/// <summary> /// Checks out a file /// </summary> /// <param name="web">The web to process</param> /// <param name="serverRelativeUrl">The server relative url of the file to checkout</param> public static void CheckOutFile(this Web web, string serverRelativeUrl) { var file = web.GetFileByServerRelativeUrl(serverRelativeUrl); var scope = new ConditionalScope(web.Context, () => file.ServerObjectIsNull.Value != true && file.Exists && file.CheckOutType == CheckOutType.None); using (scope.StartScope()) { web.Context.Load(file); } web.Context.ExecuteQueryRetry(); if (scope.TestResult.Value) { file.CheckOut(); web.Context.ExecuteQueryRetry(); } }
public static void ConditionalScope() { ClientContext cc = GetClientContext(); var file = cc.Web.GetFileByServerRelativeUrl("Site/Demo/Shared%20Documents/th.jpg"); ConditionalScope cs = new ConditionalScope(cc, () => file.Exists, true); //cc.Load(file); //Console.WriteLine(file.Exists); using (cs.StartScope()) { file.ListItemAllFields["Test"] = "StartIfTrue"; file.ListItemAllFields.Update(); } cc.ExecuteQuery(); if (cs.TestResult.HasValue) { Console.WriteLine(cs.TestResult.Value); } }
protected override bool OnProcessCheckExistence() { this.clientTermSet = null; this.localizedNameQueries = null; TermGroupUploader groupUploader = (TermGroupUploader)this.GetParentUploader(); if (!groupUploader.FoundClientObject) { this.WaitForBlocker(groupUploader); return(false); } Debug.Assert(groupUploader.ClientTermGroup != null); this.SetClientWorkingLanguageToDefault(); using (this.Controller.ClientConnector.WorkingLanguageManager.StartUnmanagedScope(this.ClientTermStore)) { this.exceptionHandlingScope = new ExceptionHandlingScope(this.ClientContext); using (this.exceptionHandlingScope.StartScope()) { using (this.exceptionHandlingScope.StartTry()) { if (this.FindByName) { CsomHelpers.FlushCachedProperties(groupUploader.ClientTermGroup.TermSets); this.clientTermSet = groupUploader.ClientTermGroup.TermSets .GetByName(this.localTermSet.Name); } else { // TODO: If "elsewhere" isn't needed, then we // can get this directly from groupUploader.ClientChildTermSets CsomHelpers.FlushCachedProperties(this.ClientTermStore); this.clientTermSet = this.ClientTermStore .GetTermSet(this.localTermSet.Id); } var conditionalScope = new ConditionalScope(this.ClientContext, () => this.clientTermSet.ServerObjectIsNull.Value, allowAllActions: true); using (conditionalScope.StartScope()) { using (conditionalScope.StartIfFalse()) { // TODO: If SyncAction.DeleteExtraChildItems==false, then we can skip this this.ClientContext.Load(this.clientTermSet, ts => ts.Id, ts => ts.Name, ts => ts.Group.Id, ts => ts.CustomProperties, ts => ts.Stakeholders, // For AssignClientChildItems() // TODO: We can sometimes skip this ts => ts.Terms.Include(t => t.Id) ); this.localizedNameQueries = TermSetLocalizedNameQuery.Load( this.clientTermSet, this.Controller.ClientLcids, this.Controller.DefaultLanguageLcid, this.ClientTermStore, this.Controller.ClientConnector ); } } } using (this.exceptionHandlingScope.StartCatch()) { } } } return(true); }
/// <summary> /// Iterates the row from the CSV file /// </summary> /// <param name="entries">The collection values per row.</param> /// <param name="logger">The logger.</param> public override void IterateCollection(Collection<string> entries, LogHelper logger) { Stopwatch IterationSW = new Stopwatch(); IterationSW.Start(); logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, "Establishing context object to: '{0}'", entries[this.SiteIndex])); try { // Use context of current iteration URL for current user item using (ClientContext context = new ClientContext(entries[this.SiteIndex])) { using (SecureString password = new SecureString()) { foreach (char c in this.Password.ToCharArray()) { password.AppendChar(c); } context.Credentials = new SharePointOnlineCredentials(this.UserName, password); // Get file to upload from directory FileInfo theFileToUpload = new FileInfo(Path.Combine(this.DirectoryLocation + "\\", entries[this.FileIndex] + ".xlsx")); logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, "Attempting to {0} file {1}", this.DocumentAction, theFileToUpload)); // Ensure account has permissions to access BasePermissions perm = new BasePermissions(); perm.Set(PermissionKind.AddListItems); ConditionalScope scope = new ConditionalScope(context, () => context.Web.DoesUserHavePermissions(perm).Value); using(scope.StartScope()) { Stopwatch tempSW = new Stopwatch(); tempSW.Start(); int success = 0; while(tempSW.Elapsed.TotalSeconds < 20) { var digest = context.GetFormDigestDirect(); string cookie = ((SharePointOnlineCredentials)context.Credentials).GetAuthenticationCookie(new Uri(entries[this.SiteIndex])).TrimStart("SPOIDCRL=".ToCharArray()); using (Stream s = theFileToUpload.OpenRead()) { // Define REST string request to upload document to context string theTargetUri = string.Format(CultureInfo.CurrentCulture, "{0}/_api/web/lists/getByTitle('Documents')/RootFolder/Files/add(url='{1}',overwrite='true')?", entries[this.SiteIndex], this.FileUploadName); // Define REST HTTP request obkect HttpWebRequest SPORequest = (HttpWebRequest)HttpWebRequest.Create(theTargetUri); // Define HTTP request action method if (this.DocumentAction == "Upload") { SPORequest.Method = "POST"; } else if (this.DocumentAction == "Delete") { SPORequest.Method = "DELETE"; } else { logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, "There was a problem with the HTTP request in DocumentAction attribute of XML file")); throw new Exception("The HTTP Request operation is not supported, please check the value of DocumentAction in the XML file"); } // Build out additional HTTP request details SPORequest.Accept = "application/json;odata=verbose"; SPORequest.Headers.Add("X-RequestDigest", digest.DigestValue); SPORequest.ContentLength = s.Length; SPORequest.ContentType = "application/octet-stream"; // Handle authentication to context through cookie SPORequest.CookieContainer = new CookieContainer(); SPORequest.CookieContainer.Add(new Cookie("SPOIDCRL", cookie, string.Empty, new Uri(entries[this.SiteIndex]).Authority)); // Perform file upload/deletion using (Stream requestStream = SPORequest.GetRequestStream()) { s.CopyTo(requestStream); } // Get HTTP response to determine success of operation HttpWebResponse SPOResponse = (HttpWebResponse)SPORequest.GetResponse(); logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, "Successfully '{0}' file {1}", this.DocumentAction, theFileToUpload)); logger.LogOutcome(entries[this.SiteIndex], "SUCCCESS"); success = 1; // Dispose of the HTTP response SPOResponse.Close(); break; } } tempSW.Stop(); if (success != 1) { throw new Exception("The HTTP Request operation exceeded the timeout of 20 seconds"); } } } } } catch(Exception ex) { logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, "There was an issue performing '{0}' on to the URL '{1}' with exception: {2}", this.DocumentAction, entries[this.SiteIndex], ex.Message)); logger.LogOutcome(entries[this.SiteIndex], "FAILURE"); } finally { IterationSW.Stop(); logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, "Completed processing URL:'{0}' in {1} seconds", entries[this.SiteIndex], IterationSW.ElapsedMilliseconds/1000)); } }
/// <summary> /// Iterates the row from the CSV file /// </summary> /// <param name="entries">The collection values per row.</param> /// <param name="logger">The logger.</param> public override void IterateCollection(Collection <string> entries, LogHelper logger) { Stopwatch IterationSW = new Stopwatch(); IterationSW.Start(); logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, "Establishing context object to: '{0}'", entries[this.SiteIndex])); try { // Use context of current iteration URL for current user item using (ClientContext context = new ClientContext(entries[this.SiteIndex])) { using (SecureString password = new SecureString()) { foreach (char c in this.Password.ToCharArray()) { password.AppendChar(c); } context.Credentials = new SharePointOnlineCredentials(this.UserName, password); // Get file to upload from directory FileInfo theFileToUpload = new FileInfo(Path.Combine(this.DirectoryLocation + "\\", entries[this.FileIndex] + ".xlsx")); logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, "Attempting to {0} file {1}", this.DocumentAction, theFileToUpload)); // Ensure account has permissions to access BasePermissions perm = new BasePermissions(); perm.Set(PermissionKind.AddListItems); ConditionalScope scope = new ConditionalScope(context, () => context.Web.DoesUserHavePermissions(perm).Value); using (scope.StartScope()) { Stopwatch tempSW = new Stopwatch(); tempSW.Start(); int success = 0; while (tempSW.Elapsed.TotalSeconds < 20) { var digest = context.GetFormDigestDirect(); string cookie = ((SharePointOnlineCredentials)context.Credentials).GetAuthenticationCookie(new Uri(entries[this.SiteIndex])).TrimStart("SPOIDCRL=".ToCharArray()); using (Stream s = theFileToUpload.OpenRead()) { // Define REST string request to upload document to context string theTargetUri = string.Format(CultureInfo.CurrentCulture, "{0}/_api/web/lists/getByTitle('Documents')/RootFolder/Files/add(url='{1}',overwrite='true')?", entries[this.SiteIndex], this.FileUploadName); // Define REST HTTP request obkect HttpWebRequest SPORequest = (HttpWebRequest)HttpWebRequest.Create(theTargetUri); // Define HTTP request action method if (this.DocumentAction == "Upload") { SPORequest.Method = "POST"; } else if (this.DocumentAction == "Delete") { SPORequest.Method = "DELETE"; } else { logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, "There was a problem with the HTTP request in DocumentAction attribute of XML file")); throw new Exception("The HTTP Request operation is not supported, please check the value of DocumentAction in the XML file"); } // Build out additional HTTP request details SPORequest.Accept = "application/json;odata=verbose"; SPORequest.Headers.Add("X-RequestDigest", digest.DigestValue); SPORequest.ContentLength = s.Length; SPORequest.ContentType = "application/octet-stream"; // Handle authentication to context through cookie SPORequest.CookieContainer = new CookieContainer(); SPORequest.CookieContainer.Add(new Cookie("SPOIDCRL", cookie, string.Empty, new Uri(entries[this.SiteIndex]).Authority)); // Perform file upload/deletion using (Stream requestStream = SPORequest.GetRequestStream()) { s.CopyTo(requestStream); } // Get HTTP response to determine success of operation HttpWebResponse SPOResponse = (HttpWebResponse)SPORequest.GetResponse(); logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, "Successfully '{0}' file {1}", this.DocumentAction, theFileToUpload)); logger.LogOutcome(entries[this.SiteIndex], "SUCCCESS"); success = 1; // Dispose of the HTTP response SPOResponse.Close(); break; } } tempSW.Stop(); if (success != 1) { throw new Exception("The HTTP Request operation exceeded the timeout of 20 seconds"); } } } } } catch (Exception ex) { logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, "There was an issue performing '{0}' on to the URL '{1}' with exception: {2}", this.DocumentAction, entries[this.SiteIndex], ex.Message)); logger.LogOutcome(entries[this.SiteIndex], "FAILURE"); } finally { IterationSW.Stop(); logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, "Completed processing URL:'{0}' in {1} seconds", entries[this.SiteIndex], IterationSW.ElapsedMilliseconds / 1000)); } }
private string TryCreateList(String listTitle, SPRemoteEventProperties properties) { string errorMessage = String.Empty; using (ClientContext clientContext = TokenHelper.CreateAppEventClientContext(properties, useAppWeb: false)) { if (clientContext != null) { // Get references to the objects needed later. ListCollection allLists = clientContext.Web.Lists; IEnumerable<List> matchingLists = clientContext.LoadQuery(allLists.Where(list => list.Title == listTitle)); clientContext.ExecuteQuery(); var foundList = matchingLists.FirstOrDefault(); List createdList = null; // Delegate the rollback logic to the SharePoint server. ExceptionHandlingScope scope = new ExceptionHandlingScope(clientContext); using (scope.StartScope()) { using (scope.StartTry()) { // SharePoint might be retrying the event after a time-out, so // check to see if there's already a list with that name. // If there isn't, create it. ConditionalScope condScope = new ConditionalScope(clientContext, () => foundList.ServerObjectIsNull.Value == true, true); using (condScope.StartScope()) { ListCreationInformation listInfo = new ListCreationInformation(); listInfo.Title = listTitle; listInfo.TemplateType = (int)ListTemplateType.GenericList; listInfo.Url = listTitle; createdList = clientContext.Web.Lists.Add(listInfo); } // To test that your StartCatch block runs, uncomment the following two lines // and put them somewhere in the StartTry block. //List fakeList = clientContext.Web.Lists.GetByTitle("NoSuchList"); //clientContext.Load(fakeList); } using (scope.StartCatch()) { // Check to see if the try code got far enough to create the list before it errored. // If it did, roll this change back by deleting the list. ConditionalScope condScope = new ConditionalScope(clientContext, () => createdList.ServerObjectIsNull.Value != true, true); using (condScope.StartScope()) { createdList.DeleteObject(); } } using (scope.StartFinally()) { } } clientContext.ExecuteQuery(); if (scope.HasException) { errorMessage = String.Format("{0}: {1}; {2}; {3}; {4}; {5}", scope.ServerErrorTypeName, scope.ErrorMessage, scope.ServerErrorDetails, scope.ServerErrorValue, scope.ServerStackTrace, scope.ServerErrorCode); } } } return errorMessage; }
private string TryRecycleList(String listTitle, SPRemoteEventProperties properties) { string errorMessage = String.Empty; using (ClientContext clientContext = TokenHelper.CreateAppEventClientContext(properties, useAppWeb: false)) { if (clientContext != null) { // Get references to all the objects you are going to need. ListCollection allLists = clientContext.Web.Lists; IEnumerable<List> matchingLists = clientContext.LoadQuery(allLists.Where(list => list.Title == listTitle)); RecycleBinItemCollection bin = clientContext.Web.RecycleBin; IEnumerable<RecycleBinItem> matchingRecycleBinItems = clientContext.LoadQuery(bin.Where(item => item.Title == listTitle)); clientContext.ExecuteQuery(); List foundList = matchingLists.FirstOrDefault(); RecycleBinItem recycledList = matchingRecycleBinItems.FirstOrDefault(); // Delegate the rollback logic to the SharePoint server. ExceptionHandlingScope scope = new ExceptionHandlingScope(clientContext); using (scope.StartScope()) { using (scope.StartTry()) { // Check to see that a user hasn't already recycled the list in the SharePoint UI. // If it is still there, recycle it. ConditionalScope condScope = new ConditionalScope(clientContext, () => foundList.ServerObjectIsNull.Value == false, true); using (condScope.StartScope()) { // Looks crazy to test for nullity inside a test for nullity, // but without this inner test, foundList.Recycle() throws a null reference // exception when the client side runtime is creating the XML to // send to the server. if (foundList != null) { foundList.Recycle(); } } // To test that your StartCatch block runs, uncomment the following two lines // and put them somewhere in the StartTry block. //List fakeList = clientContext.Web.Lists.GetByTitle("NoSuchList"); //clientContext.Load(fakeList); } using (scope.StartCatch()) { // Check to see that the list is in the Recycle Bin. // A user might have manually deleted the list from the Recycle Bin, // or StartTry block may have errored before it recycled the list. // If it is in the Recycle Bin, restore it. ConditionalScope condScope = new ConditionalScope(clientContext, () => recycledList.ServerObjectIsNull.Value == false, true); using (condScope.StartScope()) { // Another test within a test to avoid a null reference. if (recycledList != null) { recycledList.Restore(); } } } using (scope.StartFinally()) { } } clientContext.ExecuteQuery(); if (scope.HasException) { errorMessage = String.Format("{0}: {1}; {2}; {3}; {4}; {5}", scope.ServerErrorTypeName, scope.ErrorMessage, scope.ServerErrorDetails, scope.ServerErrorValue, scope.ServerStackTrace, scope.ServerErrorCode); } } } return errorMessage; }
protected override bool OnProcessCheckExistence() { this.clientTerm = null; this.clientTermOtherInstance = null; this.descriptionResultsByLcid = null; this.termLinkSourcePathPartLookups = null; this.termLinkSourcePathExceptionHandlingScope = null; TermContainerUploader parentUploader = (TermContainerUploader)this.GetParentUploader(); if (!parentUploader.FoundClientObject) { this.WaitForBlocker(parentUploader); return(false); } TermSetUploader termSetUploader = this.GetTermSetUploader(); if (!termSetUploader.FoundClientObject) { this.WaitForBlocker(termSetUploader); return(false); } if (this.localTerm.TermKind != LocalTermKind.NormalTerm) { if (!this.LoadClientTermOtherInstanceForTermLink()) { return(false); } } if (this.FindByName) { Debug.Assert(this.localTerm.TermKind == LocalTermKind.NormalTerm || this.localTerm.TermKind == LocalTermKind.TermLinkUsingPath); // TODO: If "elsewhere" isn't needed, then we // can get this directly from parentUploader.ClientChildTerms CsomHelpers.FlushCachedProperties(parentUploader.ClientTermContainer.Terms); this.SetClientWorkingLanguageToDefault(); this.exceptionHandlingScope = new ExceptionHandlingScope(this.ClientContext); using (this.exceptionHandlingScope.StartScope()) { using (this.exceptionHandlingScope.StartTry()) { this.clientTerm = parentUploader.ClientTermContainer.Terms .GetByName(this.localTerm.Name); this.ClientContext.Load(this.clientTerm, t => t.Id, t => t.Name, t => t.IsReused, t => t.IsSourceTerm, t => t.IsPinned, t => t.IsPinnedRoot, t => t.CustomProperties, t => t.LocalCustomProperties, t => t.Labels.Include( label => label.IsDefaultForLanguage, label => label.Language, label => label.Value ), // For AssignClientChildItems() // TODO: We can sometimes skip this t => t.Terms.Include(ct => ct.Id) ); this.descriptionResultsByLcid = new Dictionary <int, ClientResult <string> >(); foreach (int lcid in this.Controller.ClientLcids) { CsomHelpers.FlushCachedProperties(this.clientTerm); ClientResult <string> result = this.clientTerm.GetDescription(lcid); this.descriptionResultsByLcid.Add(lcid, result); } } using (this.exceptionHandlingScope.StartCatch()) { } } } else { Debug.Assert(this.localTerm.TermKind == LocalTermKind.NormalTerm || this.localTerm.TermKind == LocalTermKind.TermLinkUsingId); this.SetClientWorkingLanguageToDefault(); // The term/link is considered "missing" unless it's somewhere in the intended term set, // since otherwise it's ambiguous which instance should be moved/deleted/etc CsomHelpers.FlushCachedProperties(this.ClientTermStore); this.clientTerm = termSetUploader.ClientTermSet.GetTerm(this.localTerm.Id); this.ClientContext.Load(this.clientTerm, t => t.Id, t => t.Name, t => t.IsReused, t => t.IsSourceTerm, t => t.IsPinned, t => t.IsPinnedRoot, t => t.CustomProperties, t => t.LocalCustomProperties, t => t.Labels.Include( label => label.IsDefaultForLanguage, label => label.Language, label => label.Value ), t => t.Parent.Id, // For AssignClientChildItems() // TODO: We can sometimes skip this t => t.Terms.Include(ct => ct.Id) ); // If we didn't find it in this term set, then do an expensive query to find // all other instances. var scope = new ConditionalScope(this.ClientContext, () => this.clientTerm.ServerObjectIsNull.Value, allowAllActions: true); using (scope.StartScope()) { if (this.clientTermOtherInstance == null) { using (scope.StartIfTrue()) { CsomHelpers.FlushCachedProperties(this.ClientTermStore); this.clientTermOtherInstance = this.ClientTermStore .GetTerm(this.localTerm.Id); this.ClientContext.Load(this.clientTermOtherInstance, t => t.Id, t => t.Name, t => t.IsReused, t => t.IsSourceTerm, t => t.IsPinned, t => t.IsPinnedRoot ); } } using (scope.StartIfFalse()) { this.descriptionResultsByLcid = new Dictionary <int, ClientResult <string> >(); foreach (int lcid in this.Controller.ClientLcids) { CsomHelpers.FlushCachedProperties(this.clientTerm); ClientResult <string> result = this.clientTerm.GetDescription(lcid); this.descriptionResultsByLcid.Add(lcid, result); } } } } return(true); }
private string TryCreateList(String listTitle, SPRemoteEventProperties properties) { string errorMessage = String.Empty; using (ClientContext clientContext = TokenHelper.CreateAppEventClientContext(properties, useAppWeb: false)) { if (clientContext != null) { // Get references to the objects needed later. ListCollection allLists = clientContext.Web.Lists; IEnumerable <List> matchingLists = clientContext.LoadQuery(allLists.Where(list => list.Title == listTitle)); clientContext.ExecuteQuery(); var foundList = matchingLists.FirstOrDefault(); List createdList = null; // Delegate the rollback logic to the SharePoint server. ExceptionHandlingScope scope = new ExceptionHandlingScope(clientContext); using (scope.StartScope()) { using (scope.StartTry()) { // SharePoint might be retrying the event after a time-out, so // check to see if there's already a list with that name. // If there isn't, create it. ConditionalScope condScope = new ConditionalScope(clientContext, () => foundList.ServerObjectIsNull.Value == true, true); using (condScope.StartScope()) { ListCreationInformation listInfo = new ListCreationInformation(); listInfo.Title = listTitle; listInfo.TemplateType = (int)ListTemplateType.GenericList; listInfo.Url = listTitle; createdList = clientContext.Web.Lists.Add(listInfo); } // To test that your StartCatch block runs, uncomment the following two lines // and put them somewhere in the StartTry block. //List fakeList = clientContext.Web.Lists.GetByTitle("NoSuchList"); //clientContext.Load(fakeList); } using (scope.StartCatch()) { // Check to see if the try code got far enough to create the list before it errored. // If it did, roll this change back by deleting the list. ConditionalScope condScope = new ConditionalScope(clientContext, () => createdList.ServerObjectIsNull.Value != true, true); using (condScope.StartScope()) { createdList.DeleteObject(); } } using (scope.StartFinally()) { } } clientContext.ExecuteQuery(); if (scope.HasException) { errorMessage = String.Format("{0}: {1}; {2}; {3}; {4}; {5}", scope.ServerErrorTypeName, scope.ErrorMessage, scope.ServerErrorDetails, scope.ServerErrorValue, scope.ServerStackTrace, scope.ServerErrorCode); } } } return(errorMessage); }
private string TryRecycleList(String listTitle, SPRemoteEventProperties properties) { string errorMessage = String.Empty; using (ClientContext clientContext = TokenHelper.CreateAppEventClientContext(properties, useAppWeb: false)) { if (clientContext != null) { // Get references to all the objects you are going to need. ListCollection allLists = clientContext.Web.Lists; IEnumerable <List> matchingLists = clientContext.LoadQuery(allLists.Where(list => list.Title == listTitle)); RecycleBinItemCollection bin = clientContext.Web.RecycleBin; IEnumerable <RecycleBinItem> matchingRecycleBinItems = clientContext.LoadQuery(bin.Where(item => item.Title == listTitle)); clientContext.ExecuteQuery(); List foundList = matchingLists.FirstOrDefault(); RecycleBinItem recycledList = matchingRecycleBinItems.FirstOrDefault(); // Delegate the rollback logic to the SharePoint server. ExceptionHandlingScope scope = new ExceptionHandlingScope(clientContext); using (scope.StartScope()) { using (scope.StartTry()) { // Check to see that a user hasn't already recycled the list in the SharePoint UI. // If it is still there, recycle it. ConditionalScope condScope = new ConditionalScope(clientContext, () => foundList.ServerObjectIsNull.Value == false, true); using (condScope.StartScope()) { // Looks crazy to test for nullity inside a test for nullity, // but without this inner test, foundList.Recycle() throws a null reference // exception when the client side runtime is creating the XML to // send to the server. if (foundList != null) { foundList.Recycle(); } } // To test that your StartCatch block runs, uncomment the following two lines // and put them somewhere in the StartTry block. //List fakeList = clientContext.Web.Lists.GetByTitle("NoSuchList"); //clientContext.Load(fakeList); } using (scope.StartCatch()) { // Check to see that the list is in the Recycle Bin. // A user might have manually deleted the list from the Recycle Bin, // or StartTry block may have errored before it recycled the list. // If it is in the Recycle Bin, restore it. ConditionalScope condScope = new ConditionalScope(clientContext, () => recycledList.ServerObjectIsNull.Value == false, true); using (condScope.StartScope()) { // Another test within a test to avoid a null reference. if (recycledList != null) { recycledList.Restore(); } } } using (scope.StartFinally()) { } } clientContext.ExecuteQuery(); if (scope.HasException) { errorMessage = String.Format("{0}: {1}; {2}; {3}; {4}; {5}", scope.ServerErrorTypeName, scope.ErrorMessage, scope.ServerErrorDetails, scope.ServerErrorValue, scope.ServerStackTrace, scope.ServerErrorCode); } } } return(errorMessage); }