Hello kind readers…
With SharePoint 2010 the client object model specially the ECMA script model is something I just adore… it just makes life so easy. There are countless great features but one of the good one's that I recently liked it the feature activation functionality. To understand what I am talking about lets look at a scenario.
Scenario:
You have a big team and Sandboxed solution ... and everyone working on different modules creating there own solutions as a separate reusable entity with all having some features in their solutions. There are a lot of features and the sequence is important hence you set the default activation off. Now we need is a master feature to automate which can go ahead and activate all the features in the site collection, you can write another feature to do this programmatically but in that case since all your solutions are divided you would need the respective dll's as a part of your package to call code in those solutions… which is painful when there are lot feature receivers attached to those features. Plus being server code, one change in something means re deploying that master solution.
Approach:
Client object model (COM)… more than a library a tool.. That makes all your wishes come true :)… when working with sandboxed solutions COM is like the mother of all! Now with the COM library you get the classes to activate the feature on the site. How.. Well here is how…
$(document).ready(function () {
//You can also wire it up with a button click if not on page load
ExecuteOrDelayUntilScriptLoaded(ActivateFeatures, "sp.js");
});
function ActivateFeatures() {
// Guids of the required feature, you would need the full GUID including curly braces. The order you add the GUID is the order in which they start getting activated
var sFeatureGuids = new Array("{GUID}", "{GUID}",….);
//You can create the array in many ways, like if you want dynamically you can have a config list in you root site where you can add the GUID and then pick up from there, there can be many other ways...
SiteCollectionFeaturesActivate(sFeatureGuids);
}
function SiteCollectionFeaturesActivate(sFeatureGuids) {
//Loop through all the guids in the array and add
//them to the site features for activating site collection features
var clientContext = SP.ClientContext.get_current();
var site = clientContext.get_site();
for (var guid in sFeatureGuids) {
var guid = new SP.Guid(sFeatureGuids[guid]);
var featDefinition = site.get_features().add(guid, false, SP.FeatureDefinitionScope.site);
//to add new feature first get the feature collection from the site and then call add method passing the GUID, boolean for using force or not and the scope of the feature.
}
//No need to load any objects, directly calling the query is enough
clientContext.executeQueryAsync(Function.createDelegate(this, this.OnSuccessSiteFeatures), Function.createDelegate(this, this.OnFailSiteFeautres));
}
function OnSuccessSiteFeatures(sender, args) {
alert('Site Collection Features Activated Successfully');
}
function OnFailSiteFeautres(sender, args) {
alert('Fail: ' + args.get_message() + '\n' + args.get_stackTrace());
}
That’s it and you are done, now this will activate all the site collection features irrespective of which WSP they belong .
Now you would also want to activate the web features for your sites BUT... when you look at the scope enumeration for COM there are only three scopes defined for the features,
Which means you can’t activate web level features… aaaaaaaaaaannnhhhh wrong.. You CAN activate the web level features, before falling prey to the poorly documented MSDN material (not always true though) you should know that you can acitvate the web level features the same way as the site level , I mean the scope SP.FeatureDefinitionScope.site works for activating web level features too. The only difference in code is that instead of
var clientContext = SP.ClientContext.get_current();
var site = clientContext.get_site();
You do
var clientContext = SP.ClientContext.get_current();
var web= clientContext.get_web();
And add the feature GUID to the feature collection of the web.
This all gives you great deal of flexibility that you can use to make you solution more efficient and time saving… because now with this solution all you have a is a JavaScript file doing everything for you so if any changes come to your activation code can just be done to the JS file and uploaded back in the library .. No need to redeploy the code and all. I find that very convenient.
There are of course some shortcomings too.. Like if you have a feature already activated somewhere then the execution will stop there and break out saying feature already activated but you can of course put in better code to check for that first :). Other thing is that with COM you can only get the immediate child web collection of any site, which means if you have a large hierarchy of sites you can loop all webs directly like in server code SPSite.AllWebs is not there in COM, well there are a number of ways you can over come that.. :)
This can also be used for on premise solutions. There so much to explore and write but I guess this is the base , hope it helps :)
- "T"