DNN - Implementing IUpgradeable for a module's business controller class
I have to acknowledge, it has probably been more than a couple of years since I have done any real DNN (formerly DotNetNuke) development. Quite a few things seem to have changed in this time, especially with DNN 7.x.
One of those changes I got stumped on recently was implementing IUpgradeable interface on Imbibe's DNN cache provider module's business controller class. As a DNN developer, you might be aware the IUpgradeable interface implementation allows you to execute custom actions during your module's installation or upgradation process. I needed to add an item to DNN's schedule as well as a custom admin page for the cache provider module in its implementation.
The last time I implemented IUpgradeable interface should well have been more than a few years ago. That time, it was as simple as implementing the interface on the controller class and specifing the class in the <businessControllerClass> section of the module's manifest file. The same did not work this time unfortunately and no matter what I did, the logic in the UpgradeModule method won't execute on either module installation or upgradation.
After going back and forth a few times, and opening up DNN's source, it appeared it had something to do with DNN's event processing infrastructure using its EventMessageProcessor class. I then thought of taking a look into how DNN's own built-in modules implemented this interface. After checking one or two modules, it appeared DNN's Taxonomy module implemented this interface. Checking TaxonomyController did not reveal anything interesting, a regular IUpgradeable implementation. Opening up the module's manifest file (Taxonomy.dnn) next and examining it carefully brought up a new aspect, the <eventMessage> section in the manifest file, that looks like this in the Taxonomy module.
<eventMessage> <processorType>DotNetNuke.Entities.Modules.EventMessageProcessor, DotNetNuke</processorType> <processorCommand>UpgradeModule</processorCommand> <attributes> <businessControllerClass>DotNetNuke.Modules.Taxonomy.TaxonomyController, DotNetNuke.Modules.Taxonomy</businessControllerClass> <desktopModuleID>[DESKTOPMODULEID]</desktopModuleID> <upgradeVersionsList>01.00.00,06.00.00</upgradeVersionsList> </attributes> </eventMessage>
And when I co-related this section with my research into DNN's source code, it started to make sense. Unlike earlier where DNN would just see the interface implementation and execute it, DNN now requires an explicit event message to be present in the module's manifest file providing all the details on what the module is expecting to be done on its behalf by DNN (this information is kept in EventQueue table by DNN).
Also unlike earlier where DNN executed the UpgradeModule implementation for each data provider file version (e.g. 01.00.00.SqlDataProvider), it now needs the module to clearly state the versions list for which UpgradeModule should be called in the <upgradeVersionsList> element.
Thinking about these changes later made sense. Module developers earlier often needed to provide empty DataProvider files for specific versions just so DNN would call UpgradeModule for those versions when the module is upgraded for an installation. Allowing to specify it explicitly instead provides more control and flexibility to module developers.
So in my case, I had to add this <eventMessage> in the manifest file to get DNN to invoke UpgradeModule for us.
<eventMessage> <processorType>DotNetNuke.Entities.Modules.EventMessageProcessor, DotNetNuke</processorType> <processorCommand>UpgradeModule</processorCommand> <attributes> <businessControllerClass>Imbibe.Dnn.CachingProvider.OutputCache.TabCacheController, Imbibe.Dnn.CachingProvider</businessControllerClass> <desktopModuleID>[DESKTOPMODULEID]</desktopModuleID> <upgradeVersionsList>01.00.00</upgradeVersionsList> </attributes> </eventMessage>
Please note the <eventMessage> element goes as a direct child of the <component> element (and not inside <desktopModule> or <moduleDefinition> elements). [DESKTOPMODULEID] acts as a placeholder that DNN replaces dynamically for your module. The <upgradeVersionsList> is a comma-separated list of versions and DNN invokes UpgradeModule for each version in this list. The usual rules apply (i.e. UpgradeModule is only called for versions listed which are later than the currently installed version and earlier than the version listed in the package element; which means it won't be invoked at all if you just re-install an already installed version).
This is my guess but I think these changes are related to the manifest file's version too. I was using 5.0 version manifest. Not sure if DNN 7.x still supports it, but 3.0 version manifests did not need an explicit <eventMessage> to be registered for IUpgradeable implementations.
You can't really leave technology for long, it changes sooner than you get a hang of it these days