Use IRuntimeFilter to Show and Hide WebParts

Recently I presented a session at the UK Office developer conference and as part of the session I covered using the WSS 2.0 WebPart frameworks IRuntimeFilter to hide/show web parts on a page. I wasn’t that amazed that no one in the audience had ever heard of IRuntimeFilter due to the lack of documentation and samples on using it.

In this document I attempt to explain how to use it and supply the code that was shown to the UK Developer Conference attendees. It must be noted that the code samples have not been thoroughly tested and don’t necessarily adhere to best practices e.g. there is no exception handling. The code is merely there to give you and understanding of how it could be used.

By implementing IRuntimeFilter you are essentially creating a rule or a set of rules that determine if a web part should be displayed or not. For example:

  1. SharePoint Portal Server (SPS) uses a IRuntimeFilter for audiences. A user will setup the audiences that are allowed to see a web part (using the advanced section in the web part’s toolpane), then when a user visits the web page the filter runs and determines if the web part should be shown or not. If a virtual server is extended with SPS then the Microsoft.SharePoint.Portal.Audience.AudienceManager filter is installed by default.
  2. You could create a custom IRuntimeFilter that determines if a web part should be displayed based on the WSS role the user is a member of. This is what the sample code in this document does
  3. You could create a custom IRuntimeFilter that determines if a web part should be displayed based on any arbitrary property or rule(s) that you come up with.

Note:
You can only have one IRuntimeFilter per virtual server. Therefore you cannot have the SPS audience and a custom filter running on the same virtual server.

STEPS

1. Create a Class that implements IRuntimeFilter

Create a class that implements IRuntimeFilter. Compile, sign and add the assembly to the GAC.

The IRuntimeFilter requires that you implement the following methods:

  • CheckRuntimeRender
  • InitializeStrings
  • IsFilterActive
  • ValidateIsIncludedFilter

1.1 CheckRuntimeRender
This method tells the web part framework whether it should show the web part or not. If this method returns true then the web part will be shown, if it returns false the web part will not be shown.
This is where you implement your rule(s) to determine if the web part should be displayed.
The method has a single string parameter which is set the value of the string returned from the pop-up dialog box. This dialog box is discussed in the next section.

Sample:
//return true to show web part or false to hide
public bool CheckRuntimeRender(String filter)
{
//check if current user can see the web part
return CanUserSeePart(filter);
}

1.2 InitializeStrings
The InitializeStrings method tells the web part framework what the web part toolpart should look like so that a user can select a button to open up the pop-up dialog box. As shown in the image below.

 toolpart

The method returns an arraylist that holds the definition for the toolpart. The first item in the arraylist defines the text for the label, the second defines the tooltip for the label, the third defines the text on the button and the fourth defines the pop-up window attributes.

Sample:
//define what to show in toolbar
public ArrayList InitializeStrings(CultureInfo cultureInfO)
{
ArrayList strings = new ArrayList();
strings.Add("Role Picker");
strings.Add("Lets you pick which user roles can view this web part");
strings.Add("Pick Role");
strings.Add("dialogHeight:340px;dialogWidth:430px;help:no;status:no;resizable:no");
return strings;
}

1.3 IsFilterActive
This method determines if the filter is active for the current web part or not. If the filter is not active then the toolpart picker will not be shown and the rules will not execute. This method should return true if the filter is active and false if not.
If a virtual server is extended with SPS then the default filter that is installed (Microsoft.SharePoint.Portal.Audience.AudienceManager) will return false if the web part is running on a WSS site and will return true if the web part is running in an SPS area. Therefore you only get the Audience chooser pop-up in SPS sites.

Sample:
//is the filter active for this site
public bool IsFilterActive()
{
return true;
}

1.4 ValidateIsIncludedFilter
This method allows you to validate and correct the return value of pop-up dialog window. For example you could determine if the user selection is actually a valid one.
The method has a single string parameter which is set to the return value from the dialog window. The method returns a string which should be the value you want to persist to the web part, i.e. the value that will be a parameter in the CheckRuntimeRender method.

Sample:
//check that the values in the IsIncludedFilter property are valid before they are saved to the database.
public string ValidateIsIncludedFilter(string persistedString)
{
//assume that the value is fine and just return it
return persistedString;
}

The class must be compiled into a .Net assembly with a strong name and then added to the GAC

2. Create Pop-up dialog web page
This is the pop-up window that the user will be presented with when he/she selects the button in the toolpart to set the rules for the filter e.g. when the user selects “Role Picker” or “Select Audiences”. The sample Role Picker dialog can be seen below.

 

RolePicker

The logic behind this web page is entirely up to the developer and depends on what the requirements for the filter are. In this specific sample the user can select a single WSS role from a drop down list, only the selected role is allowed to view the web part.

Tip:
In this sample the list is a drop down list that limits the user to a single choice, perhaps a series of checkboxes would have been better.

If you want to be able to access the WSS API in the context of the current site it is recommended that you create the pop-up windows as an ASP .Net page (.aspx) in an ASP .Net project in the _layouts folder.
When the user selects “OK”, you must return the users chosen data as a string. This string is what is in turn sent into the filter’s ValidateIsIncludedFilter method as a string parameter.
Sample script code for when user selects OK in rolepicker.aspx:

<script language="javascript">
if(window.dialogArguments)
{

//this shows what the previous setting was for filter, comment out for now
//alert(window.dialogArguments.value);
}

//execute when the user selects OK
function OnOkClick()
{
//get the value from the currently selected item in the listbox called lstRoles
var value = window.document.all.lstRoles.options[window.document.all.lstRoles.selectedIndex].value;
window.returnValue = value;
window.close();
}
</script>

Sample code in rolepicker.aspx page load method:

SPWeb currentWeb = SPControl.GetContextWeb(Context);
foreach (SPRole role in currentWeb.Roles)
{
lstRoles.Items.Add(role.Name);
}

3. Edit Web.Config to point to new filter
By default the web.config for the virtual server point to the SPS Audience IRuntimeFilter, this needs to be changed to point to the custom filter. Importantly set the BuilderURL attribute to the path of the pop-up dialog window. This is relative the _layouts/1033/ folder, as you can see in the sample below my rolepicker.aspx was located in /_layouts/devcon/.

Sample:
<RuntimeFilter Assembly="DevConRunTimeFilter, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b9e17e23dc48e734" Class="DevConRunTimeFilter.RuntimeFilter" BuilderURL="../devcon/rolepicker.aspx" />

In the attached ZIP file are .Net 3 projects

1. DevConRunTimeFilter – this is the class library project that contains the IRuntimeFilter class.
2. DevCon – this in an ASP .Net project containing the rolepicker.aspx
3. User – this is an ASP .Net web service that determines the role a use is a member of

Important
It is not recommended to call a web service from the IRuntimeFilter as my sample does. This was done purely to demonstrate functionality and was a quick way of solving an issue with the WSS API. Essentially you should be looking to execute the methods in the filter as quickly as possible.
For information purposes: the issue with the WSS API is that users cannot execute the API to determine what WSS role they are a member of, unless the user is a site administrator. This was solved in this sample code by using a web service and calling the service under the context of an administrator. This problem is detailed in Maurice’s blog here https://www.bluedoglimited.com/SharePointThoughts/Log/DisplayLog.aspx?ID=7.
Also, you could use another technique for holding roles e.g. custom list.