Wednesday 16 July 2014

Access Denied when using SPSite.AllWebs

As I have been working to develop a web part that our organization will use to present roll-up data from multiple sub-sites to a top-level site, I've come across a n interesting tid bit that was frustrating at first.
It is the use of SPSite.AllWebs property. Check this code:
ArrayList Lists = new ArrayList();
SPSite CurrentSite = SPContext.Current.Site;
SPContentTypeId ContentType = new SPContentTypeId(PARENT_CONTENT_TYPE);
SPWebCollection UserSites = CurrentSite.AllWebs;
foreach (SPWeb web in UserSites)
{
foreach (SPList list in web.Lists)
{
if (list.ContentTypesEnabled)
{
try
{
bool ContainsType = false;
SPContentTypeCollection Types = list.ContentTypes;
foreach (SPContentType Item in Types)
{
if (Item.Id.IsChildOf(ContentType))
{
ContainsType = true;
break;
}
}
if (ContainsType)
{
Lists.Add(list);
}
}
catch
{
}
}
}
When running as an administrator, this code doesn't cause a single problem. However, if you swap to a non-administrative user that doesn't have full control of the site, you'll get the lovely access denied page. The problem is that you must have full control of the site to be able to use the AllWebs property.
The fix for this is to use a property of the SPWeb object. See the corrected code below:
ArrayList Lists = new ArrayList();
SPSite CurrentSite = SPContext.Current.Site;
SPContentTypeId ContentType = new SPContentTypeId(PARENT_CONTENT_TYPE);
SPWebCollection UserSites = CurrentSite.OpenWeb().GetSubwebsForCurrentUser();
foreach (SPWeb web in UserSites)
{
foreach (SPList list in web.Lists)
{
if (list.ContentTypesEnabled)
{
try
{
bool ContainsType = false;
SPContentTypeCollection Types = list.ContentTypes;
foreach (SPContentType Item in Types)
{
if (Item.Id.IsChildOf(ContentType))
{
ContainsType = true;
break;
}
}
if (ContainsType)
{
Lists.Add(list);
}
}
catch
{
}
}
}
By using the GetSubwebsForCurrentUser() method, I'm able to get a list of subsites that the user does have access to view. If the user doesn't have access to any subsites, there will not be the access denied error message and you can display a warning to the user.