In a Building an Accordion with jQuery and SharePoint 2010 | dig sharepoint, I showed you how to build an accordion style menu using SharePoint 2010 and jQuery. I recently had a request to expand on this idea by personalizing the items shown based on which SharePoint Group users belonged to. What came to mind was to use Audience Targeting.
Here is another custom webpart I built that shows items from a SharePoint list, and using an ASP.Net Repeater control, I display them in a specified order:
I was approached with a challenge of only showing items from the list for certain users. At first I thought I could have used item level permissions, but then I thought using Audience Targeting would be a better option. When researching Audience Targeting, most searches I found involved setting up the User Profile Service and then using a Content Query Webpart to filter who sees the data. In my case, I didn’t need a CQWP as I already had a custom webpart to display list content. Initially I thought that by removing the “RunWithElevatedPrivileges” context when retrieving list data would filter list items in a list/library view by the Target Audience specified in that column. However, this did not produce the desired outcome, as the item priviledges are based on item level permissions.
Here is what I ended up doing to get Audience Targeting to work for me:
The first step is to setup a method to retrieve list data. The following shows a standard way of getting all list data without regard to item level permissions:
public static DataTable GetListData(string listName, string xmlQuery)
{
DataTable dt = new DataTable();
DataTable dtNew = new DataTable();
SPSite site = SPContext.Current.Site;
SPWeb web = SPContext.Current.Web;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite ElevatedSite = new SPSite(site.ID))
{
using (SPWeb ElevatedWeb = ElevatedSite.OpenWeb(web.ID))
{
SPList theList = ElevatedWeb.Lists[listName];
SPQuery query = new SPQuery();
query.Query = xmlQuery;
SPListItemCollection items = theList.GetItems(query);
dt = items.GetDataTable();
// Factor in those items for specific audiences
dtNew = GetListDataIncludingTargetAudience(dt);
}
}
});
return dtNew;
}
The next step involves setting up your list with Audience Targeting:
- Site Actions –> View All Site Content –> <List Name>
- List Settings –> Audience Targeting Settings
- Enable audience targeting
- List Settings –> <View> –> <Click to Modify>
- Add the new “Target Audiences” to the current view.
Now that your list is setup, whenever you edit a list item, you can add the SharePoint Group to the “Target Audiences” field using the People Picker:
- Click on the ‘Browse’ icon, search for your new SharePoint Group, and click ‘OK’.
- Click ‘Save’ on the item, and you should now see it listed in the “Target Audience” column for this item.
public static DataTable GetListDataIncludingTargetAudience(DataTable dt)
{
// Perform audience targeting on list items: http://msdn.microsoft.com/en-us/library/ms563693.aspx
// Fill dtNew with Audience specific list items
AudienceLoader audienceLoader = AudienceLoader.GetAudienceLoader();
DataTable dtNew = new DataTable();
dtNew = dt.Clone();
for (int z = 0; z <= dt.Rows.Count - 1; z++)
{
// Check to see if this is a valid column
if (dt.Columns.Contains("Target_x0020_Audiences"))
{
string audienceFieldValue = dt.Rows[z]["Target_x0020_Audiences"].ToString(); // (string)listItem[k_AudienceColumn];
// If the value is empy, then assume it is for every audience
if (audienceFieldValue == string.Empty)
dtNew.ImportRow(dt.Rows[z]);
else
{
// quickly check if the user belongs to any of those roles.
// Add the data row if user is a member of the audience targeted item.
if (AudienceManager.IsCurrentUserInAudienceOf(audienceLoader, audienceFieldValue, false))
dtNew.ImportRow(dt.Rows[z]);
}
}
else
{
// Add the item if audience targeted column does not exist
dtNew.ImportRow(dt.Rows[z]);
}
}
return dtNew;
}
- It first looks to see if there is a column called “Target_x0020_Audiences”.
- If it does not exist, then we want to continue on and still import the row into a new DataTable. By doing it this way, we won’t be filtering out data…we will be filtering “in” data if the column exists.
- If the column exists, it then performs a check to see if the currently logged in user is a part of the SharePoint Group found for the particular DataTable Row. It does this using the AudienceManager class. With this class you can retrieve individual types, lists of audiences, and lists of users who are associated with an audience. If the user a part of the Audience, this item will be imported into a new DataTable. If the user does not belong to the Audience, it will not be imported.
I found that using the Target Audience feature on a list is a great built-in feature to SharePoint 2010. Using it to include more data for a specific group adds a little personalization that can be easily implemented. Please test it out for yourself and let me know how it works out for you!