Will "the Mighty" Strohl

HOW TO: Create a DotNetNuke® Skin Object

Disclaimer:  This blog entry assumes that you have prior experience and knowledge creating and installing modules.

Skin Objects in DotNetNuke® offer functionality that the skin designer can plan for, but not need to know how to create.  But what is a skin object?  It is a .Net User Control that offers a functionality that you want offered to the skin, but not as a module. 

There are plenty of reasons why you would want to create a skin object over a module.  For example, anyone with administrator or edit permissions can alter the functionality of that module.  Examples of a skin object are: Login, Search, Menu, Breadcrumb, and more.  You might notice a common trend among all of those examples.  None of them need to be managed after the skin is complete.  So why allow someone with edit permissions to tinker with it once it is on the site?

No matter what you skin object is supposed to do, remember one thing.  You need to expose public properties that allow for settings and CSS to be defined by the designer in the skin.xml.

Essentially, there are usually only four significant differences between a skin object and a module. The first difference is that you cannot automatically generate an installation package for a skin object like you can with a module.

The second difference is that the Skin Object does not need the Edit and Setting controls that you normally include in the development of a module.  There is no interface available to manage skin objects, and there shouldn't be.  That would completely defeat the purpose of skin objects.

Coming in as the third difference is the inherited class.  While you can still inherit from the PortalModuleBase class, you should be inheriting from the DotNetNuke.UI.Skins.SkinObjectBase class instead.

The fourth and final difference, and this is the most important one, is that the manifest file has two distinct differences.  If your manifest file is not correctly defined, the skin object will not install as a skin object, but rather install as a module or not install at all.

Here is an example of a typical module manifest file:

<dotnetnuke version="3.0" type="Module">
  <folders>
    <folder>
      <name>MyModule</name>
      <friendlyname>MyCompany Customer History</friendlyname>
      <foldername>MyModule</foldername>
      <modulename>MyModule</modulename>
      <description>The MyCompany Customer History Module allows you to give the web site visitors a way to view and manage their activity history.</description>
      <version>01.02.02</version>
      <businesscontrollerclass>MyCompany.Modules.MyModule.MyModuleController</businesscontrollerclass>
      <modules>
        <module>
          <friendlyname>MyCompany Customer History</friendlyname>
          <cachetime>-1</cachetime>
          <controls>
            <control>
              <src>DesktopModules/MyModule/MyModuleView.ascx</src>
              <type>View</type>
            </control>
            <control>
              <key>Settings</key>
              <title>MyCompany Customer Info Settings</title>
              <src>DesktopModules/MyModule/Settings.ascx</src>
              <type>Edit</type>
            </control>
          </controls>
        </module>
      </modules>
      <files>
        <file>
          <path>App_LocalResources</path>
          <name>MyModuleView.ascx.resx</name>
        </file>
        <file>
          <path>App_LocalResources</path>
          <name>Settings.ascx.resx</name>
        </file>
        <file>
          <path>images</path>
          <name>Cancel.png</name>
        </file>
        <file>
          <path>images</path>
          <name>Confirmed.png</name>
        </file>
        <file>
          <name>module.css</name>
        </file>
        <file>
          <name>MyModuleView.ascx</name>
        </file>
        <file>
          <name>MyModuleView.ascx.vb</name>
        </file>
        <file>
          <name>Settings.ascx</name>
        </file>
        <file>
          <name>Settings.ascx.vb</name>
        </file>
        <file>
          <path>[app_code]</path>
          <name>MyModuleController.vb</name>
        </file>
      </files>
    </folder>
  </folders>
</dotnetnuke>

You probably do not see anything out of the ordinary there (unless you've never created a module).   Now here is an example of a skin object manifest file.

<dotnetnuke version="3.0" type="SkinObject">
  <folders>
    <folder>
      <name>MyModuleSkinObject</name>
      <version>01.01.02</version>
      <modules>
        <module>
          <friendlyname>MyCompany Customer History Skin Object</friendlyname>
          <controls>
            <control>
              <key>MyModuleLINK</key>
              <title>MyCompany Customer History Skinobject</title>
              <src>MyModuleLink.ascx</src>
              <type>SkinObject</type>
            </control>
          </controls>
        </module>
      </modules>
      <files>
        <file>
          <name>MyModuleLink.ascx</name>
        </file>
        <file>
          <name>MyModuleLink.ascx.vb</name>
        </file>
        <file>
          <path>App_LocalResources</path>
          <name>MyModuleLink.ascx.resx</name>
        </file>
      </files>
    </folder>
  </folders>
</dotnetnuke>

This probably doesn't look a whole lot different at first glance.  Take a look at the first node, at the Type attribute.  Notice that instead of the value Module, it now is the value SkinObject.  That is the most important difference. 

The other difference is that you will see much less code in the manifest file.  This is because we do not need as much definition for the skin object files for a couple of reasons.  First, there are not as many files to define.  Second, the definition of the remaining files do not require the same treatment, as there are fewer nodes needed to tell DotNetNuke® how to display the user controls.  There is only one way.

That's it!  I bet you thought it was MUCH more complicated than that.  Huh?



blog comments powered by Disqus