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.

Friday, July 10, 2009

Debug Sharepoint Event Receiver

Debugging is kind of important when developing a new application. In case of event receiver it is more important as errors are not visible unless they are logged in the text files or in the event log. For event receiver, you cannot start application with F5; you need to set the break point in the code, and wait until item is added or deleted from list.

Furthermore, event receiver DLL needs to be in GAC. It cannot be deployed in the bin folder of web application like web part DLL. It means that, for debugging, your PDB (symbols database) has to be in GAC as well. This is what everybody recommends. Since you can only add DLLs in GAC, there is no straight way how to do that. A simple trick which always works is to place PDB file in the bin folder of web application.

This is the how you can debug event receiver without adding PDB file in the GAC.

1) Right click on project properties of Event Receiver project
2) Go to Build tab
3) Change Output path: to c:\Inetpub\wwwroot\wss\VirtualDirectories\$webApplication$\bin\ where $webApplication$ is you web application folder
4) Build project in Debug mode to create the PDB file and DLL in the \bin of web application
5) If GAC has DLL build in the Release mode, uninstall it
6) Copy or install DLL (Debug mode build) file from web application's \bin folder to (GAC) c:\Windows\Assembly folder
7) Reset IIS Server
8) Hit any page on the SharePoint 2007 web application. It will load W3WP.exe.
9) Attach Debugger to W3WP.exe. If you have multiple W3WP.exe select process by user name
10) Perform add, delete or update operation on a list. Debugger will hit first break point. Make sure to replace DLL in the GAC with every code change.