Monday, April 4, 2011

Limited Access Permission

The Limited Access permission level is used to give users\groups access to a specific list, library, folder, document, or item, without giving them access to the entire site. If this permission level is removed, the users\groups might not be able to navigate through the site to get the specific items, even if they have the correct permissions for an item within the site.

You cannot edit this permission level directly. This is special permission and introduced in the SharePoint 2007, to support the item level permissions. In the previous version of SharePoint item level permission was not there. As mentioned earlier it is mostly use for navigational purpose. Though you have limited access permission on the list you will not see items or folders in the list unless you have given privileges on the items or folder.

For an example I have SharePoint site with following hierarchy
Team Site->Parent->Shared Documents (Document Library)-> ‘Temp Folder’ (Folder).

If I give unique permission on ‘Temp Folder’ to ‘User1’ by breaking Role Inheritance, SharePoint will provide ‘Limited Access’ permission on all the parent objects of ‘Temp Folder’. That means ‘User1’ will get Limited access to Shared Documents, Parent and Team Site. But ‘User1’ will only view items on which he has been given access other than ‘Limited Access’, directly. So if  Shared Documents has one more folder say ‘Temp1 Folder’, ‘User1’ will get ‘Limited Access’ on this folder as by default it inherits permission from its parent ‘Shared Documents’. But ‘User1’ will not see ‘Temp1 Folder’ unless ‘User1’ is given more privileges on this folder.

How to assign Limited Access privileges programmatically?

SharePoint doesn’t allow assigning ‘Limited Access’ privileges directly. You need follow work around. Work around is, if you want to give ‘Limited Access’ on Document Library, create folder in document library, Break Role Inheritance for this folder, give user other SharePoint permission to this folder , say ‘Read Only’ and remove the same permission in next step. When you add unique permission on the folder, SharePoint assigns ‘Limited Access’ to parent of folder to ensure that user can navigate to folder with unique permissions, but when you remove permission; it doesn’t remove ‘Limited Access’ permission from parent object.

//Assign user permission on the Folder

oWeb.AllowUnsafeUpdates = true;
SPRoleDefinition oRoleDefinition = oWeb.RoleDefinitions[PermissionLevel];
SPRoleAssignment oAssignment = new SPRoleAssignment(oUser.LoginName, oUser.Email,oUser.Name, oUser.Notes);
oAssignment.RoleDefinitionBindings.Add(oRoleDefinition);
oLstItem.RoleAssignments.Add(oAssignment);

//Remove user permission on the Folder

oLstItm.RoleAssignments.Remove((SPPrincipal)oUser);
oLstItm.Update();

Limited Access example in real life

You can only open bank locker with your key, but to get to the locker, you need have locker room door key as well. You have full access to locker, but limited access to locker room door.

SPWeb.Lists Vs SPWeb.GetList

There are many posts on this topic. So why I am writing one more post? Well just to share my experience and hope others will benefit from this.

SPWeb.GetList (string strUrl) – Good
using (SPSite site = new SPSite(strSite))
{
      using (SPWeb web = site.OpenWeb())
            {
                SPList oList = web.GetList(http://Site/list/AllItem.aspx)
            }
 }

In this case, first retrieves the list GUID from the url (database hit), then it loads the metadata* for that specific list.

SPWeb.Lists (“name”) – Not Good
using (SPSite site = new SPSite(strSite))
{
    using (SPWeb web = site.OpenWeb())
           {
              SPList oList = web.Lists ["MyList"]
           }
 }

In this case, it loads the metadata* of the all lists in that specific SPWeb object. Then it does SPList.Title comparison with metadata of all the lists returned and then it returns the matching list from the SPWeb.Lists collection.

Most of the posts have recommended using SPWeb.GetList (string url) instead of SPWeb.Lists [“”] to get list instance. Logically, SPWeb.GetList seems to be more performance oriented compared to the retrieving collection of lists, because first method tries to get Guid to retrieve the list and later populates list collection and then retrieving one of the items. So I started changing all calls made to get list from SPWeb.Lists [“listName”] to SPWeb.GetList (“/lists/listName”) in SharePoint application. To my surprise code was performing 5 times slower than previous version. I had used ANTS Performance Profiler tool to profile SharePoint application.

In my opinion following are reasons which has caused application to perform badly after change.
1) SPWeb.Lists [] pulls information for all the lists in one attempt. This call may be slow, but once information is available in the memory, going through list collection is faster than database call. If SharePoint web site has 25 lists, only one call is made and data retrieved is reused for further processing.
2) SPWeb.GetList () makes separate database call for each and every list for which information needs to be pulled. So if you have 25 lists to work with, 25 calls will be made. It makes overall performance of application slow.

Our SharePoint environment has 250,000 lists. (10,000 sub sites X 25 lists). Though this environment has so many list, as list are scoped at web level, loading collection of 25 list is much faster than loading individual list on every call. Loading collection will consume more memory, compare to loading individual list, but once all the lists are loaded in the memory one by one, memory foot print will be same as loading entire list collection once.

Conclusion: For web with moderate numbers of list it is better to use SPWeb.Lists []. Do not get overwhelmed with total number of lists in the site collection. SPWeb.GetList will perform better compared to SPWeb.Lists [], if number of lists in the web are large (I don’t have idea what that number is. If you have 1000s of list in web it may be time to rethink of your design.).

Don’t follow all best practice blindly unless it’s coming
1) directly coming from Microsoft
2) applicable to your problem.