If you read my last post, Creating Audiences via STSADM, then you know that I've been working on a project which requires me to be able to script out the creation of audiences via STSADM. My last post covered the creation of the audience itself, but an audience with no rules isn't all that useful, so for this post I'll be covering my next custom command, gl-addaudiencerule, which enables you to add complex rules to an audience.
I'll reiterate a couple of things regarding creating rules from my last post. First off, when you create rules via the browser you are limited to just simple rules - in other words, you may have multiple rules but the boolean logic is limited to all rules matching or any rules matching - there is no combination or complex boolean logic with grouping. This is not the case if you create the rules programmatically - by programmatically creating the rules we can use grouping (up to 3 levels deep) and any combination of boolean logic. The catch is that as soon as you add any complex rules to an audience you will now no longer be able to manage that audience via the browser - you'll still be able to compile the audience and view memberships but you won't be able to manage or even view any rules associated with the audience and you won't be able to delete the audience. I created two more commands that allow you to see the rules and delete the audience via STSADM but I'll talk about them in follow-up posts.
Microsoft took an interesting approach to storing the rules - they basically use an ArrayList of objects of type AudienceRuleComponent. Each object represents a part of the rule, including the the parentheses and logic operators (AND, OR). So a rule like the following would consist of 7 objects:
(Department == "IT" OR Reports Under == "domain\glapointe") AND IsContractor == false
The above would be broken down into objects in the following fashion:
- new AudienceRuleComponent(null, "(", null);
- new AudienceRuleComponent("Department", "=", "IT");
- new AudienceRuleComponent(null, "OR", null);
- new AudienceRuleComponent("Everyone", "Reports Under", "domain\glapointe");
- new AudienceRuleComponent(null, ")", null);
- new AudienceRuleComponent(null, "AND", null);
- new AudienceRuleComponent("IsContractor", "=", "false");
The objects created above would be added to the rules collection array list in the order listed. One thing you may have noticed above is that the field for the "reports under" operation is "Everyone" - the field for the "member of" operation is actually "DL". It's important to note that if you change the rules you must reassign the AudienceRules property rather than manipulate the items via the property:
- audience.AudienceRules.Add(new AudienceRuleComponent(null, "(", null)); // This will not work as the property will not be marked as dirty and will therefore not be saved when Commit is called.
- ArrayList rules = audience.AudienceRules;
rules..Add(new AudienceRuleComponent(null, "(", null));
audience.AudienceRules = rules; // This assignment marks the audience rules as dirty and will thus be saved.
The way I decided to handle the creation of these rules was to allow a simple XML structure to be passed into the command either directly via a parameter or indirectly by passing in a file containing the rules. The structure of the XML is similar to the structure of the above code - you create one or more <rule /> elements which are wrapped in a <rules /> element. The <rule /> element contains one required attribute, "op", and two optional (depending on the operation) attributes, "field" and "value". Grouping operations do not require the field and value attributes and member of and reports under operations do not require the field attribute. Here's an example of the above:
The help for the command is shown below:
C:\>stsadm -help gl-addaudiencerule stsadm -o gl-addaudiencerule Adds simple or complex rules to an existing audience. The rules XML should be in the following format: <rules><rule op='' field='' value='' /></rules> Values for the "op" attribute can be any of "=,>,>=,<,<=,<>,Contains,Not contains,Reports Under,Member Of,AND,OR,(,)" The "field" attribute is not required if "op" is any of "Reports Under,Member Of,AND,OR,(,)" The "value" attribute is not required if "op" is any of "AND,OR,(,)" Note that if your rules contain any grouping or mixed logic then you will not be able to manage the rule via the browser. Example: <rules><rule op='Member of' value='sales department' /><rule op='AND' /><rule op='Contains' field='Department'value='Sales' /></rules> Parameters: -name <audience name> -rules <rules xml> | -rulesfile <xml file containing the rules> [-ssp <SSP name>] [-clear (clear existing rules)] [-compile] [-groupexisting (wraps any existing rules in parantheses)] [-appendop <and (default) | or> (operator used to append to existing rules)]
The following table summarizes the command and its various parameters:
|Command Name||Availability||Build Date|
|Parameter Name||Short Form||Required||Description||Example Usage|
|name||n||Yes||This is the name of the audience for which to apply the rules.||-name "IT Department"
-n "IT Department"
|ssp||No||The name of the SSP that the audience is associated with. If not specified then the default SSP is used.||-ssp SSP1|
|rules||r||Yes - unless rulesfile provided||The XML rules that are to be created. Use tick marks instead of quotes. Using this parameter, as opposed to the rulesfile parameter, is convenient when using a batch script in which you'd like to pass variables into the XML.||-rules "<rules><rule op='(' /><rule field='Department' op='=' value='IT' /><rule op='or' /><rule op='reports under' value='domain\glapointe' /><rule op=')' /><rule op='and' /><rule field='IsContractor' op='=' value='false' /></rules>"|
|rulesfile||rf||Yes - unless rules provided||Specifies the path to an XML file containing the rules to be created. The file extension does not matter. Using this parameter, as opposed to the rules parameter, is convenient when you'd like to save your rules for later reference or recreation in other environments as well as easy modification.||-rulesfile c:\Audiences\ITDepartment.rules|
|clear||cl||No||If provided then any existing rules will be removed from the audience.||-clear
|compile||co||No||If provided then the audience will be compiled after adding the rules.||-compile
|groupexisting||group||No||If provided then any existing rules will be grouped within parentheses.||-groupexisting
|appendop||op||No||Specifies how the passed in rules will be appended to any existing rules. Valid values are "and" or "or". The default, if omitted, is "and".||-appendop or
The following is an example of how to add rules to an audience named "IT Department":
stsadm -o gl-addaudiencerule -name "IT Department" -rules "<rules><rule op='(' /><rule field='Department' op='=' value='IT' /><rule op='or' /><rule op='reports under' value='domain\glapointe' /><rule op=')' /><rule op='and' /><rule field='IsContractor' op='=' value='false' /></rules>" -clear -compile