Linq to SharePoint. Part 3

Part 1. First()/FirstOrDefault(), T-SQL IN, Path
Part 2. Count(), Take(), Skip(), JOIN, ObjectTracking
Part 3. Anonymous access, Resolve list by URL
Part 4. Dynamic LINQ, Convert SPListItem to data context object
Part 5. Choice and MultiChoice fields

Resolve list by URL

There is GetList<T> method in Microsoft.SharePoint.Linq.DataContext class used for creating custom data context. This methos takes string value representing Title of the list. And then tere are two problems: waht to do with localization and what to do if the list is renamed by user.

Another pair of shoes is a list' URL: user can's change it and localiztion doesn't matter. But there is no any method that returns a list by its URL in the SharePoint API. To resolve this trouble you can use SPWeb.GetFolder(string strUrl) method. The result of it is SPFolder object that contains ParentListId property. Following method represents this trick:

  1. /// <summary>
  2. /// Resolve list by URL
  3. /// </summary>
  4. private EntityList<T> GetListByUrl<T>(string listUrl)
  5. {
  6.     string listTitle;
  7.     using(var site = new SPSite(Web))
  8.     {
  9.         using(var web = site.OpenWeb())
  10.         {
  11.             var folder = web.GetFolder(listUrl);
  12.             var list = web.Lists[folder.ParentListId];
  13.             listTitle = list.Title;
  14.         }
  15.     }
  16.     return GetList<T>(listTitle);
  17. }

The method is cool, but also has a limit: URL must be site relative. Like these:

"/Lists/Departments", "Lists/Departments", "/Lists/Departments/AllItems.aspx", "/DocLib/Forms/AllItems.aspx"

This method works some slower 'cause of initialation of these object: SPSite, SPWeb, SPFolder and SPList.

Anonymous access

There is another trouble with user Linq to SharePoint: it can't work in anonymous access mode. The reason is this: SPContext.Current.Web.CurrentUser property in anonymous access mode is NULL. And SharePoint throw up an exception. It's enough to check out the constructor of SPServerDataConnection class (it used for retrieving data from SharePoint lists) to understand how to resolve it:

  1. public SPServerDataConnection(string url)
  2. {
  3.     if (SPContext.Current != null)
  4.     {
  5.         this.defaultSite = SPContext.Current.Site;
  6.         this.defaultWeb = (SPContext.Current.Web.Url == url) 
  7.             ? SPContext.Current.Web 
  8.             : this.defaultSite.OpenWeb(new Uri(url).PathAndQuery);
  9.     }
  10.     else
  11.     {
  12.         this.defaultSite = new SPSite(url);
  13.         this.defaultWeb = this.defaultSite.OpenWeb(new Uri(url).PathAndQuery);
  14.     }
  15.     if (!this.defaultWeb.Exists)
  16.     {
  17.         throw new ArgumentException(
  18.             Resources.GetString("CannotFindWeb"new object[] { url }));
  19.     }
  20.     this.defaultWebUrl = this.defaultWeb.ServerRelativeUrl;
  21.     this.openedWebs = new Dictionary<string, SPWeb>();
  22.     this.openedWebs.Add(this.defaultWebUrl, this.defaultWeb);
  23. }

If current context is null it re-created using current URL. This is the first point. The second one is that it's necessary someone account to impersonate it. We can use SPSecurity.RunWithElevatedPrivileges static method, which execute delegate trasfered to it with full control rights. Following code executtes method with full control right if the current user is null:

  1. public static void RunAsAdmin(SPSecurity.CodeToRunElevated secureCode)
  2. {
  3.     // Anonymous access flag
  4.     var isAnonymous = SPContext.Current.Web.CurrentUser == null;
  5.     // Is it necessary to reset current context
  6.     var nullUserFlag = (SPContext.Current != null && isAnonymous);
  7.  
  8.     if (nullUserFlag)
  9.     {
  10.         // Save current context
  11.         var backupCtx = HttpContext.Current;
  12.         // Reset current context
  13.         HttpContext.Current = null;
  14.         // Execute code
  15.         SPSecurity.RunWithElevatedPrivileges(secureCode);
  16.         // Restore the context
  17.         HttpContext.Current = backupCtx;
  18.     }
  19.     else
  20.     {
  21.         // Execute as is
  22.         SPSecurity.RunWithElevatedPrivileges(secureCode);
  23.     }
  24. }

This static method may be used inside custom data context.

That's something like this.


Share

Comments