Packaging Modules for DotNetNuke 5
So, the first thing I noticed when testing Events in [DNN] 5 was that it seemed like some of our shared base assemblies weren't being updated to the latest version that comes with Events. Looking into it further, I realized that those assemblies were associated with the other Engage module I had installed on the site, Engage: Locator. The short story is that [DNN] now keeps track of assemblies when you install them, to help keep assemblies from being uninstalled or overwritten incorrectly. When you install a [DNN] 4 module, it appears that it sets the version of the assemblies that it installs to the version of the module. So, I had installed Locator 1.4, which gave Engage.Dnn.Framework.dll a version of 1.4.0 in the [DNN] database. When I installed Events 1.1, [DNN] thought it was an older version of Engage.Dnn.Framework.dll (1.1.0), even though it was actually the most recent version.
So, to help fix this as much as we could, I decided it was time to figure out this 5.0 packaging stuff and create a 5.0 package for Engage: Events. First, I asked [DNN] to make a module package of Events, based on the [DNN] 4 package I had installed. I looked through that and updated and removed parts to get it closer to what we wanted. Specifically, I removed the <eventMessage> section from the Module component, since... I couldn't figure out any reason we'd need that. I think it might be necessary now if you implement IUpgradeable, but it's best to try it out for yourself.
I also removed all of the files other than scripts, cleanup, and assemblies, since we use a Resource File .zip to avoid having to change the manifest whenever the content files in the module change. In [DNN] 4 manifests, this looked like a <resourceFile> element in the <folder> element for your module, pointing to the file to unzip with all of your files. In [DNN] 5, that didn't work. After a bit of searching, I found Erik's blog post, DotNetNuke 5 Extention Packaging. This helped my a ways along my path, showing that these Resource File .zips have their own section in the manifest file. After a bit of trying to figure out why his example wasn't working for me, I figured out that he'd left out one of the elements (the interior <resourceFile>) in the XML. With that figured out, my section looks like this:
<component type="ResourceFile">
<resourceFiles>
<basePath>DesktopModules/EngageEvents</basePath>
<resourceFile>
<name>Resources.zip</name>
</resourceFile>
</resourceFiles>
</component>
Back to the first issue I had experienced, I could now specify my own versions for the assemblies that I included in the package. This isn't necessarily a magic bullet, though, until all of our modules have a [DNN] 5 package. This is because the correct version of some of the shared assemblies (e.g. Engage.Dnn.Framework.dll) is still lower than the version of some of our [DNN] 4 modules. (For example, the version of Engage.Dnn.Framework.dll released with Events is 1.1.0, but the latest version of Locator is 1.4.0). So, if those are installed, we'll see the same inability to overwrite the shared assemblies with newer versions. But, this is the first step towards getting there. Accurate information is better than inaccurate, in my book.
The next change to be made to the generated manifest is to fill in the <owner> section at the top of the package. We can supply a <name>, <organization>,<url>, and <email> that is shown when the module is installed. This makes sure people know who wrote the module and how to find us. From Erik's post, I also found out that you can include HTML in those fields, so you can make the <url> and <email> links, rather than plain text. Our section looks like this:
<owner>
<name>Engage Software</name>
<organization>Engage Software</organization>
<url><![CDATA[<a href="http://www.engagesoftware.com/">http://www.engagesoftware.com/</a>]]></url>
<email><![CDATA[<a href="mailto:support@engagemodules.com">support@engagemodules.com</a>]]></email>
</owner>
The last bit of new functionality in the manifest that I worked with is the License and Release Notes. These are new fields that users see when they install the module. We were already including a copy of the license in our [DNN] 4 packages, but now we can link to that file and make sure that users explicitly agree to it before installing the module. We also keep release notes on our website that we can now show upon install, rather than making folks search for them.
So, at this point, I think I'm done with this process. However, I try to install, and see the following:
Tracking this down, I realized that I had deleted elements with default values in the <moduleControls> section of the manifest. I didn't want to have a <viewOrder> element making it seem like someone was specifically setting that value, when really we don't care, it's just a default. Well, one of the elements I deleted was <controlKey> from the default module control. This is how our [DNN] 4 manifest looks, since the default module control doesn't have a key assigned. Looking at the error, it looked like that was no longer an acceptable practice, so I added a <controlKey/> to that <moduleControl> entry, and it worked like a charm. And, really, that makes sense. I care that <controlKey> is empty, I'm not just accepting the default value for lack of a better value, I'm actively choosing to use an empty <controlKey>.
So, those are the hassles, issues, and features that I encountered while creating a [DNN] 5 package for our module. Hopefully this'll give you some better understanding of some of what's involved, and get you more quickly around those obstacles that I ran up against.
[Cross-posted from http://www.engagesoftware.com/Blog/EntryId/194/Packaging-Modules-for-DotNetNuke-5.aspx]