Past few days I have been looking into the creation and setting up of audiences in MOSS2007. It took me a while though to figure all these things out, but I'm kind of getting the hang of it right now ;) So ... time to share it with the world, right?
For the development, we'll be using the following Assemblies:
- System.Web.UI.WebControls.WebParts
- Microsoft.Office.Server
- Microsoft.Office.Server.Audience
- Microsoft.Office.Server.Search.Administration
- Microsoft.SharePoint
- Microsoft.SharePoint.WebPartPages
(For those of you who don't know where to find the Microsoft.Office.Server dll files, it's located in the C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI folder.)
1. Creating a new audience
First thing we'll do is creating a custom audience, giving it two rules, joined with an OR operator.
public void CreateNewAudience()
{
string audienceName = "Test and temp"; //audience name
string audienceDesc = "Only the test and temp users."; //audience description
using (SPSite site = new SPSite("http://server/site"))
{
ServerContext context = ServerContext.GetContext(site);
AudienceManager audManager = new AudienceManager(context);
AudienceCollection audCollection = audManager.Audiences;
Audience audience = null;
AudienceRuleComponent audRule = null;
audience = audCollection.Create(audienceName, audienceDesc);
audience.AudienceRules = new ArrayList(); //initialize the collection
/* An AudienceRuleComponent exists of:
* a left part: the property to look at
* an operator: the operator to perform (=, <>, Contains, ...)
* a right part: the value to search for */
audRule = new AudienceRuleComponent("UserName", "Contains", "test");
audience.AudienceRules.Add(audRule);
audRule = new AudienceRuleComponent(null, "OR", null);
//to use an operator (AND, OR, ...) set the left and the right part to NULL !
audience.AudienceRules.Add(audRule);
audRule = new AudienceRuleComponent("UserName", "Contains", "temp");
audience.AudienceRules.Add(audRule);
audience.Commit(); //commit the changes
}
}
Doing this, a new audience named "Test and Temp" will be created, which in the end will contain all users with user names containing "test" or "temp".
If you would like to have a complete set of the operators, see http://msdn2.microsoft.com/en-us/library/ms954299.aspx
However, without compiling the new audience, we won't be able to do a lot with it, right?
Compiling the audience can be done in a couple different ways. We can compile it manually through the Shared Service Provider administration pages or stsadm, schedule the compilation, or do it programmatically. Guess what we are going to do ;)
2. Compiling the new audience
To compile the new audience, we have to run an AudienceJob, and give it 4 parameters in a string array:
- The application id
- "1" = start job, "0" = stop job
- "1" = full compilation, "0" = incremental compilation (optional, default = 0)
- Audience name (optional, if null is supplied, all audiences are run!
http://msdn2.microsoft.com/en-us/library/microsoft.office.server.audience.audiencejob.runaudiencejob.aspx
http://jopx.blogspot.com/2007/05/scheduling-audience-compilation-in-moss.html
public void CompileAudience()
{
using (SPSite site = new SPSite("http://server/site"))
{
ServerContext context = ServerContext.GetContext(site);
SearchContext searchContext = SearchContext.GetContext(context);
string[] args = new string[4];
args[0] = searchContext.Name;
args[1] = "1";
args[2] = "1";
args[3] = "Test and temp";
Int32 runjob = AudienceJob.RunAudienceJob(args);
}
}
So in this case, it means we will perform a START of the operation, doing a FULL compilation, on the audience TEST AND TEMP.
Oke, so now our audience has been compiled, we can go for the next step: setting up an audience on a webpart we put on a SharePoint page.
3. Audience targetting in a webpart
It took me quite a long time to figure out how to set up the audiences in a webpart through code ... I found a partial answer on Mart Muller's blog here:
http://blogs.tamtam.nl/mart/CommentView,guid,a0b20be6-56e4-4571-af0f-3dff43b5f69d.aspx
However, the solution given there does not work for me, but I might as well just have missed something there :) So, after some trial and error, I managed to get "my" version to work, by using the ID of the audience in stead of the name.
So first, we'll have to retrieve this ID from the audience we're looking for:
public Guid GetAudienceId(string audienceName)
{
using (SPSite site = new SPSite("http://server/site"))
{
ServerContext context = ServerContext.GetContext(site);
AudienceManager audManager = new AudienceManager(context);
AudienceCollection audCollection = audManager.Audiences;
foreach (Audience aud in audCollection)
{
if (aud.AudienceName == audienceName)
return aud.AudienceID;
}
}
}
Then, we add this ID to the AuthorizationFilter property of the webpart. This is where the audience parameter is set!
public void AddAudienceToWebpart()
{
using (SPSite site = new SPSite("http://server/site"))
{
using (SPWeb web = site.OpenWeb())
{
SPLimitedWebPartManager wpManager = web.GetLimitedWebPartManager("http://server/site/page.aspx", PersonalizationScope.Shared);
SPLimitedWebPartCollection wpCol = wpManager.WebParts;
foreach (System.Web.UI.WebControls.WebParts.WebPart webp in wpCol)
{
//Let's assume we want to put the audience on a webpart with title "AUDIENCE WebPart"
if (webp.Title == "AUDIENCE WebPart")
{
webp.AuthorizationFilter = GetAudienceId("Test and temp").ToString() + ";;;;";
wpManager.SaveChanges(webp);
break;
}
}
}
}
}
As you see, the AuthorizationFilter ENDS with 4 semicolons (";;;;"). According to Mart's blog, when using the name of the audiences, this string STARTS with these semicolons, but as said before, I did not get this to work properly ...
After running this, the webpart "AUDIENCE WebPart" will be targetted to our Test and temp and only the users compiled in this audience will see the webpart on the page :)