SharePoint RunTimeFilter and audiences... an investigation
In the web.config file of SharePoint Portal Server you find the line:
<RuntimeFilter Assembly="Microsoft.SharePoint.Portal, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" Class="Microsoft.SharePoint.Portal.Audience.AudienceManager" BuilderURL="audience_chooser.aspx" />
I was wondering what this line was doing here, and what other things you can implement using RunTimeFilter configurations. Fired up Google… nothing. Fired up reflector, and after some disassembling I came to the following (possibly non-valid) conclusions:
Microsoft.SharePoint.Portal.Audience.AudienceManager implements the interface Microsoft.SharePoint.WebPartPages.IRuntimeFilter.
This is an interface in the Windows SharePoint Services namespace, so my assumption is that the runtime filter mechanism is also supported in WSS.
The interface that must be implemented is:
public interface IRuntimeFilter
{
// Methods
[PermissionSet(SecurityAction.LinkDemand, Unrestricted=true)]
bool CheckRuntimeRender(string IsIncludedFilter);
[PermissionSet(SecurityAction.LinkDemand, Unrestricted=true)]
ArrayList InitializeStrings(CultureInfo cultureInfo);
[PermissionSet(SecurityAction.LinkDemand, Unrestricted=true)]
bool IsFilterActive();
[PermissionSet(SecurityAction.LinkDemand, Unrestricted=true)]
string ValidateIsIncludedFilter(string persistedString);
}
What these methods exactly should do is not documented, so after some disassembling of Microsoft.SharePoint.Portal.Audience.AudienceManager:
:
public bool IsFilterActive()
{
if (PortalApplication.GetContext() == null)
{
return false;
}
return true;
}
So this filter is only active if there is a portal context, that means only for SharePoint Portal Server, not for WSS. Makes sense for audience manager because this functionality is only available on the portal.
public bool CheckRuntimeRender(string isIncludedFilterOrg)
{
:
}
This method seams to do an intersection between the selected target audiences for a web part, and the list of audiences the current user is part of. This is probably done for each web part, because targeting to audiences can be applied per web part. This would mean that the RunTimeFilter mechanism is only there for web part filtering: is a web part displayed or not for the current user (anyone?). Intersection computation is done through the stored procedure DBO.Orgle_MatchOrgleList. If there is an intersection the web part is rendered.
public string ValidateIsIncludedFilter(string PersistedString)
{
:
}
Not sure what happens here… I think the PersistedString parameter is the string returned by the selection of the audiences. Probably a concatenation of audience ID's. There is some translation going on to guid's returning a new comma separated string of guid's.
public ArrayList InitializeStrings(CultureInfo ci)
{
:
:
}
Looks like this function does some initial initialization of a string table based on a culture… which is ignored in the AudienceManager. Still not completely understand the complex way things are implemented in this function, but the result is that the texts to be used for the functionality for targeting (the "Target Audiences" section in the "Advanced" part of web part configuration) is retrieved. Strings like "Target Audiences" and "Select" (for on the button).
The aspx page specified in the RunTimeFilter tag (BuilderURL="audience_chooser.aspx") is hooked up to the button for the selection of the audiences.
If you look at the hooked up pages for audience selection in the current implementation, you see the following code:
<%@ Page language="C#"
Inherits="Microsoft.SharePoint.Portal.SitePage,Microsoft.SharePoint.Portal,Version=11.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="SPSWC" Namespace="Microsoft.SharePoint.Portal.WebControls" Assembly="Microsoft.SharePoint.Portal, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<html dir="ltr">
<head>
<SPSWC:PageHeadTags runat="server" TitleLocId="AudienceChooser_PageTitle_Text" OldExpires="0" PageContext="SiteAdminPage"/>
<SPSWC:ExternalHtmlResourceElement runat="server" HtmlElement="Script" FileContext="SharedScript" FileName="audpicker.js" />
</head>
<body>
<form runat="server" ID="AudienceChooser2" method="POST" action="Audience_Chooser2.aspx">
<Sharepoint:FormDigest runat="server" id="FormDigest" />
<SPSWC:PageLevelError id="AudiencePageLevelError" runat="server" />
<SPSWC:AudiencePicker id="AudiencePicker" SupportRuntimeFilter="true" runat="server" />
</form>
</body>
</html>
With the actual real implementation in the server control
<SPSWC:AudiencePicker id="AudiencePicker" SupportRuntimeFilter="true" runat="server" />, meaning the class: Microsoft.SharePoint.Portal.WebControls.AudiencePicker
A simple test reveals that only one entry of RunTimeFilter is allowed in the web.config. This is a pity, it is not possible to implement your own web part display filtering on top of the existing one. If you really want to this can probably be easily done by implementing a new filter and call in this filter multiple other filters. On the other hand: if you want to change this, you probably want to change this completely.
I never was really impressed by the way that audiences were implemented. Can be that I don't really understand the intended way of usage;-) Some of my problems with it are (incomplete list):
- Audiences are precompiled, so not "real-time"
- Audiences are rules based on profile properties (coming from active directory), often there is already a company directory available in large organizations, and replication of all the needed information to the profile is not always the way you want to go
- Due to the the restricted possibilities in the audience definitions you can make I always end up with way to many audiences. For example: if you have an audience definition depending on the country and office you are in, you have to define country*office audiences, instead of targeting to a country, and/or an office
On top of my head the only places audiences are used are in listings and in web part targeting. Web part targeting can be overruled by implementing your own RunTimeFilter. For listings and the targeting in here you probably need to reimplement all the portal web parts showing listings because you have to implement your own filtering on listings.
How it works with listing I did not investigate yet. Maybe a topic for a next weblog entry!
If anyone has more info on this stuff, please reply!!!
Disclaimer: all made assumptions are speculative, based on disassembling and (I hope) some common sense.