2/11/2010

SharePoint: Application page to display all sites a user can view

 

This sample project works for both SharePoint 2007 and 2010!

This project is for educational purposes and is to be used at your own risk…

 

 

Display a list of all sites a user has rights to…

The following is a “demo” project to show the workings of several SharePoint API features:

  • Iterating through all sites in a farm
  • Checking user rights
  • Using an application page and the application master page
  • and using a SharePoint grid control (SPGridView)

What’s interesting is that the majority of the code ended up supporting the SPGridView!

 

image

With only a change to the master page (application.master to applicationV4.master) it looks like this in SharePoint 2010 (beta).

image

 

Deployment

Deploy the two files to the LAYOUTS folder on each web front end server. Best practice is to create a folder with a unique name and put your files there. Something like:

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\techtrainingnotes\mysites\

 

Then you can test the pages from any site like this:

http://maxsp2007/sites/training/_layouts/techtrainingnotes/mysites/Default.aspx

 

 

MySites.aspx

Here’s the ASPX file. Just two content tags, a dropdown list, two labels and the grid control. Note the @Register for Microsoft.SharePoint.WebControls needed for the SPGridView control.

For SharePoint 2010 you should change application.master to applicationV4.master.

 
<%@ Page Language="C#" MasterPageFile="~/_layouts/application.master" AutoEventWireup="true"
    CodeFile="Default.aspx.cs" Inherits="_Default" %>
 
<%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"
    Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
 
<asp:Content ID="Content2" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server">
    Site Access List
</asp:Content>
 
<asp:Content ID="Content1" ContentPlaceHolderID="PlaceHolderMain" runat="server">
 
    <asp:DropDownList ID="ddlScope" runat="server" AutoPostBack="True">
        <asp:ListItem Value="Site">The current Site Collection</asp:ListItem>
        <asp:ListItem Value="WebApplication">The current application</asp:ListItem>
        <asp:ListItem Value="Farm">The entire farm</asp:ListItem>
    </asp:DropDownList>
    <br />
 
    <asp:Label ID="lblCount" runat="server" Text=""></asp:Label>
    Sites available to:
    <asp:Label ID="lblUserName" runat="server" Text=""></asp:Label>
 
    <SharePoint:SPGridView runat="server" ID="SPGridView1" AutoGenerateColumns="false" />
    <SharePoint:SPGridViewPager ID="SPGridViewPager1" GridViewId="SPGridView1" runat="server" />
 
</asp:Content>

 

MySites.aspx.cs

Here’s the code for that finds the sites the user has access to. The code that does to real work here is pretty simple. The key methods are:

  • GetSiteCollectionSites(SPSite) – this iterates through the web.AllWebs collection of the SPSite and checks to see if the user has at least the “ViewPages” permission 
     
  • GetApplicationSites(SPWebApplication) – this iterates thorough the Sites collection and calls GetSiteCollectionSites for each site found
     
  • GetFarmSites() – this iterates through all of the WebApplictions in the farm and calls GetApplicationSites for each SPWebApplication found. (Note that this requires higher permissions that most users have so it has to be run using RunWithElevatedPrivileges

The rest of the code is used to setup the SPGridView.

 

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.WebControls;
using System.Data;
 
public partial class _Default : System.Web.UI.Page
{
    DataTable dt = new DataTable();
    SPUser user;
 
    protected void Page_Load(object sender, EventArgs e)
    {
        //get the logged in user
        user = SPContext.Current.Web.CurrentUser;
        lblUserName.Text = user.Name;
 
        //setup the datatable
        dt.Columns.Add("URL", typeof(string));
        dt.Columns.Add("Title", typeof(string));
        dt.Columns.Add("Description", typeof(string));
 
        //get the sites
        string scope;
        scope = ddlScope.Text;
        switch (scope)
        {
            case "Farm":
                GetFarmSites();
                break;
            case "Site":
                GetSiteCollectionSites(SPContext.Current.Web.Site);
                break;
            case "WebApplication":
                GetApplicationSites(SPContext.Current.Site.WebApplication);
                break;
        }
 
        lblCount.Text = dt.Rows.Count.ToString();
 
        //add columns to the grid
        int cols = dt.Columns.Count;
        SPGridView1.Columns.Clear();
        for (int i = 0; i < cols; i++)
        {
            if (i == 0)
            { //add hyperlink column
                HyperLinkField newColumn = new HyperLinkField();
 
                newColumn.HeaderText = dt.Columns[i].ToString();
                newColumn.DataTextField = dt.Columns[i].ToString();
                newColumn.DataNavigateUrlFields = new string[] { dt.Columns[i].ToString() };
                newColumn.DataTextFormatString = "";
                newColumn.SortExpression = dt.Columns[i].ToString();
                SPGridView1.Columns.Add(newColumn);
            }
            else
            { // add all other columns
                SPBoundField newColumn = new SPBoundField();
                newColumn.HeaderText = dt.Columns[i].ToString();
                newColumn.DataField = dt.Columns[i].ToString();
                newColumn.SortExpression = dt.Columns[i].ToString();
                SPGridView1.Columns.Add(newColumn);
            }
        }
 
        //set a default sort
        dt.DefaultView.Sort = "URL";
 
        SPGridView1.DataSource = dt;
        SPGridView1.DataBind();
        //all done
    }
 
 
    // get all webs in a site collection and see if the user has View access
    void GetSiteCollectionSites(SPSite site)
    {
        // all webs in the site collection
        foreach (SPWeb web in site.AllWebs)
        {
            if (web.DoesUserHavePermissions(user.LoginName, SPBasePermissions.ViewPages))
            {
                DataRow row = dt.NewRow();
                row["URL"] = web.Url;
                row["Title"] = web.Title;
                row["Description"] = web.Description;
                dt.Rows.Add(row);
            }
            web.Dispose();
        }
    }
 
    //get all site in an application
    void GetApplicationSites(SPWebApplication wa)
    {
        // all site collections in the application
        foreach (SPSite site in wa.Sites)
        {
            GetSiteCollectionSites(site);
            site.Dispose();
        }
    }
 
    //get all applications in the farm
    void GetFarmSites()
    {   //get all of the services
        SPWebServiceCollection webServices = new SPWebServiceCollection(SPFarm.Local);
 
        SPSecurity.RunWithElevatedPrivileges(delegate()
        {
 
            foreach (SPWebService webService in webServices)
            {   //get all of the applications from each service
                foreach (SPWebApplication webApp in webService.WebApplications)
                {
                    GetApplicationSites(webApp);
                }
            }
 
        });
    }
}

 

If I get the time… I’ll post a longer version of this that adds sorting, paging, a menu bar and some other bells and whistles .

 

.

1 comment:

Hardik Shah said...

Getting error in the code. it is working with site administrator account but for the normal user(member, visitor) it is not working. Throwing exception.
DelegateControl: Exception thrown while adding control 'ASP.SocialDataUserControl': Object reference not set to an instance of an object. c6fb33b7-3aa1-4204-ad7f-48ea3f9ba20b
10/11/2011 08:13:03.40 w3wp.exe (0x1E8C) 0x07B8 SharePoint Foundation Runtime tkau Unexpected System.NullReferenceException: Object reference not set to an instance of an object. at AllAvailableSites.Layouts.PFG.AllAvailableSites.Page_Load(Object sender, EventArgs e) at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) at System.Web.UI.Control.OnLoad(EventArgs e) at Microsoft.SharePoint.WebControls.UnsecuredLayoutsPageBase.OnLoad(EventArgs e) at Microsoft.SharePoint.WebControls.LayoutsPageBase.OnLoad(EventArgs e) at System.Web.UI.Control.LoadRecursive() at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) c6fb33b7-3aa1-4204-ad7f-48ea3f9ba20b

Please help me out.

Note to spammers!

Spammers, don't waste your time... all posts are moderated. If your comment includes unrelated links, is advertising, or just pure spam, it will never be seen.