SharePoint security trimmed site list
Okay, so it has been a bit since I have posted anything, mainly due to that I have not anything notable to post. This is not due to me not doing anything notable but that the things that I have done that were notable were proprietary and I did not feel comfortable disclosing in a public forum.
So the problem that I was given was that when people landed on the root site within the root site collection of our managed path / application the user hit a page that was essentially blank. From there they did not know where they should go and did not really know what they would be able to access. So here comes a webpart that can help solve the problem. What the goal of this webpart was is to create a security trimmed list of sites the user would have access at the root level. I am not going to go through each and every step for creating a webpart but I will give some high level info since these are steps that I struggled with when creating the webpart.
- So first off, when you are creating this webpart select the "Visual Web Part option" in the project type.
- You MUST select DEPLOY AS FARM SOLUTION. The sandboxed solution will not have access to the necessary objects needed for this webpart. Specifically getting all site collections in a web application (managed path).
- To start we will create two classes. SiteLookup and SPSiteInfo.
SiteLookup
- using Microsoft.SharePoint;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace SPSiteListing.ListSPSites
- {
- class SiteLookup
- {
- private Boolean _EnableTrimming;
- private SPContext _Context;
- private string _CurrentUserName;
- public SiteLookup(SPContext context, Boolean enablePermissionTrimming)
- {
- _EnableTrimming = enablePermissionTrimming;
- _Context = context;
- _CurrentUserName = context.Web.CurrentUser.LoginName;
- }
- public List<SPSiteInfo> GetSites()
- {
- if (IsRootInApplication())
- {
- list.AddRange(GetSitesUnderCurrentWeb());
- list.AddRange(GetSitesUnderManagedPath());
- return list;
- }
- else
- return GetSitesUnderCurrentWeb();
- }
- public Boolean IsRootInApplication()
- {
- if (_Context.Site.RootWeb.Url != _Context.Site.Url)
- return false;
- if (_Context.Site.WebApplication.Sites[0].Url != _Context.Site.Url)
- return false;
- return true;
- }
- public List<SPSiteInfo> GetSitesUnderManagedPath()
- {
- var applicationSites = _Context.Site.WebApplication.Sites;
- foreach (SPSite item in applicationSites)
- {
- //you must set disable catching access exceptions to prevent sharepoint from catching it
- item.CatchAccessDeniedException = false;
- try
- {
- if (item.RootWeb.DoesUserHavePermissions(_CurrentUserName, SPBasePermissions.Open) || !_EnableTrimming)
- }
- catch (UnauthorizedAccessException)
- {
- //The user does not have access to check their access. So an exception will be thrown.
- //This will not cause a problem to not do anything with it, since we are security trimming
- //we do not want this one listed anyway.
- }
- }
- return sites;
- }
- public List<SPSiteInfo> GetSitesUnderCurrentWeb()
- {
- if (_EnableTrimming)
- {
- foreach (SPWeb item in _Context.Web.GetSubwebsForCurrentUser())
- {
- }
- }
- else
- {
- foreach (SPWeb item in _Context.Site.AllWebs)
- {
- }
- }
- return sites;
- }
- }
- }
SPSiteInfo
- using Microsoft.SharePoint;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace SPSiteListing.ListSPSites
- {
- class SPSiteInfo
- {
- public string SiteName { get; private set; }
- public string SiteUrl { get; private set; }
- public string HTMLLink
- {
- get
- {
- return String.Format(@"<a href=""{0}"">{1}</a>",
- SiteUrl,
- String.IsNullOrEmpty(SiteName) ? SiteUrl : SiteName);
- }
- }
- public SPSiteInfo(SPSite site)
- {
- try
- {
- SiteName = site.RootWeb.Title;
- }
- catch (UnauthorizedAccessException)
- {
- //since the user does not have access to get the title, we can do something
- //here if we want with demonstrating that. but it isn't necessary
- }
- SiteUrl = site.Url;
- }
- public SPSiteInfo(SPWeb site)
- {
- SiteName = site.Name;
- SiteUrl = site.Url;
- }
- }
- }
-
So now that we have the classes written to get the data, we need a something to display the data in the webpart. To do that we will use the ascx file created already (just adding a ul with an id and a runat) and add some code in the page_load method.
ASCX file
- <ul id="siteList" runat="server">
- </ul>
ASCX code behind
So that is basically it. There are some details that are not covered in this post, but this should get you past the things that I struggled with when I created my webpart.
Good Luck !!