Published: 07 Mar 2007
By: Oleg Zhukov

This article shows how to extract skin from a DotNetNuke-based portal.

Transformation rules
  Skin is filled with content
  Content consists of modules wrapped in containers
  How skin-specific ASP.NET tags are rendered
  How container-specific ASP.NET tags are rendered
Reverse engineering
  Gathering necessary files
  Creating a skin control
  Reverse engineering content panes
  Creating container controls
  Reverse engineering containers’ ASP.NET tags
  Reverse engineering skin’s ASP.NET tags
  Skin packaging


When designing a skin for a DotNetNuke portal it might be reasonable to see how skins are implemented at other DNN-based sites. However these skins may not be directly available. If this is the case the desired skin can be extracted from a DotNetNuke-based portal by following the technique described in this article.

First let us look into the lifecycle of a DotNetNuke page. Everything starts when DNN processes a skin control (*.ascx) inserting page content where needed. After the page is filled with content the control passes to the ASP.NET engine which renders the page and substitutes ASP.NET tags with proper HTML code. The resulting HTML is passed to the browser. This is a simplified description but it shows the basic mechanism of the translation from a DNN skin to the client HTML code.

The main idea expressed in the article is that with the knowledge of the translation rules we can reverse the transformation order and build the original DNN skin based on the client HTML code.

As an example we will go through reverse engineering the skin used by the portal.

Transformation rules

As we have already mentioned the translation from a DotNetNuke skin to the HTML code returned to a browser is done in two steps. Both of them obey a number of rules.

1) Skin is filled with content

The DotNetNuke engine inserts page content into content panes - in skin (*.ascx) files these panes are identified with the <td> tag. However to distinguish the content pane <td> tags from other <td> tags the former should be equipped with the runat="server" attribute.

During translation the runat attributes are removed from the content <td> tags and the dnn_ prefix is added to the id. For internal needs the <a name="..."></a> tag is also added just before the content goes. Thus the following construct in a skin control:

will result in the following HTML code:

Now let us understand what content is constituted by.

2) The content consists of modules wrapped in containers

Generally content is a number of modules encapsulated within some module containers. The Module container is described in a separate ASP.NET control file (*.ascx). During a page construction the module contents are inserted into the module container. The insertion logic here is similar to one applied during skin population – a tag with the id="ContentPane" and runat="server" attribute is found and filled with the module’s contents.

For example the following tag in a container control

will be replaced with:

3) How skin-specific ASP.NET tags are rendered

There is quite a limited number of ASP.NET tags commonly used in DNN skin controls. Here we list them and show what markup is generated for them.

4) How container-specific ASP.NET tags are rendered

Containers can also include some specific ASP.NET tags. They are listed below:

The following tag produces empty output if the user is not an administrator:

The next three tags rarely appear in containers however the reader should be aware of them:

Reverse engineering

Now when we know how a DotNetNuke skin is transformed to the client HTML code we can perform the reverse translation for the website.

First of all let us gather all necessary material. These include start page HTML code, linked CSS files and referenced images.

Gathering necessary files

Open the start homepage and choose the option in browser to show HTML code of the page (in IE6 View -> Source / in FF View -> Page source). Save the shown HTML to a new file called client.html.

In the top of the client.html find all references to the *.css stylesheet files and download these files. They usually include skin.css, container.css, default.css and portal.css. You will probably need a download manager since browsers often try to open files instead of downloading them.

Images are referenced in the *.css files with the url(...) syntax. Images in HTML code may be included with the standard HTML <img> tags and with the style=... attributes. Locate all referenced images and download them.

A convenient way to download all needed files is using some offline download manager such as SurfOffline. Point it to the homepage of a website and it will locally save all css and media files while maintaining the correct folder structure.

Creating a skin control

Since the DNN skin is an *.ascx user control it corresponds only to a part of the client HTML code. Usually it starts right after the <SPAN ID="dnn_dnnMENU_ctldnnMENU_divOuterTables"></SPAN> tags and spreads down to the <input name="ScrollTop" type="hidden" id="ScrollTop" /> tag. Copy this specified section from the client.html to a new skin.ascx file.

Supplement the Skin.ascx with the following lines at the top of it. These lines are common for every DNN skin control:

The screenshot below shows how your Skin.ascx should look like:

The Skin control now contains a copy of the client HTML code rather than real ASP.NET controls. In the following steps we will see which controls to add to retrieve the original form.

Reverse engineering content panes

In this step we will locate all content panes in the client.html. Due to the transformation rules described above the content panes in the client HTML look like displayed in the following code blocks:

There are 6 such blocks (dnn_ControlPanel, dnn_LeftPane...dnn_BottomPane). Let us supersede them with what they are generated from while copying their contents into separate files called LeftPane_Contents.html ... RightPane_Contents.html.

The below image illustrates how it should be done with the left pane:

Creating the container controls

There are three types of containers used on The first type has a visible border and a white background (for example Quick Links in the left pane). The second one is similar except its background is grey (News in the left pane). And the third container has no border (Welcome to DotNetNuke in the content pane).

The generated HTML of the first container is located at the top of the LeftPane_Contents.html file. Copy this into a new file called Container1.ascx.

Then add the following lines at the top of Container1.ascx usercontrol to make use of container-specific ASP.NET tags. These lines are used for all container controls:

According to the Transformation rules we should replace the following fragment:

which was formely generated from the below HtmlGenericControl ASP.NET control:

In the same manner let us extract Container2.ascx from the LeftPane_Contents.html and Container3.ascx from the ContentPane_Contents.html. Repeat the steps described above with these files.

Reverse engineering the containers ASP.NET tags

In the Transformation rules paragraph we have already listed possible HTML code blocks generated from container-specific ASP.NET tags. Now we will investigate these container ascx files and search for such HTML blocks and replace them with corresponding ASP.NET controls.

Almost every container has a title. And so does Container1.ascx – it contains the following code:

Substitute it with what it originated from:

For an administrator to adjust the container and inner modules we should add the container actions menu. For example insert it as follows:

Now let us take a look at referenced images in the <td> tags specified with the style attribute:

The background image used above is referenced as being relative to the website root. Since we do not want it to be bound to any particular location we should make this path relative to the container’s control. For that let us create the Container.css file and add the necessary css classes declarations as displayed below:

Then reference these classes from the container control with the class attribute:

Another place in the Container1.ascx file where images are referenced being relative to the root is in the <img> tags:

To make paths relative to the Container1.ascx file we will replace these tags with the <asp:Image> control:

Repeat this for all occurrences of <img> HTML tags in the Container1.ascx.

Repeat the above steps with Container2.ascx and Container3.ascx. After that we are finished with containers and the last step left is to bring the Skin.ascx into its original form.

Reverse engineering skin’s ASP.NET tags

Now we need to find all output HTML fragments generated from skin-specific ASP.NET controls. The search box comes first:

Replace it with:

Then find the menu. It is described with the following HTML:

We will rewrite it as follows:

Then we should reverse engineer the Register and Login links. Thus we should substitute this:

with the following:

Accordingly to Transformation rules locate the rest (copyright, terms and privacy) of the generated HTML fragments and substitute them with appropriate ASP.NET tags.

One more thing left to do is to correct some image references making them relative to the skin control rather than to the website root. The common technique here is the same as we used for container controls. That is we should replace <img> tags with <asp:Image> specifying a relative path in ImageUrl attribute. For example such image reference:

should be replaced with: The only difficulty arises when dealing with onmouseover and onmouseout client events. The following code solves the problem:

When you have converted all <img> tags we are ready to package the created skin and containers for deployment.

Skin packaging

The packaging procedure is very easy and is described in the following three steps:

  1. Skin control (ascx) along with its css files and image folders should be compressed into a single file
  2. Container controls (ascx) with accompanying css files and images (in folders) should be compressed into
  3. The resulting and should be compressed together into <SkinName>.zip

The packaging scheme for our example looks as follows:


As soon as you apply the resulting skin to a DNN portal you should get a similar result as shown below:


In this article you have learned how to extract skins from existing DotNetNuke-based websites. With this technique a skin designer is able to explore skins of any DNN portals.

However a reader must be aware that he may not use the extracted skin at his website since it is intellectual property of the skin’s owner. He may only explore the reverse engineered skin and be inspired by it to create a new skin.

For more DotNetNuke articles from Oleg Zhukov visit his website at:

<<  Previous Article Continue reading and see our next or previous articles

About Oleg Zhukov

Oleg Zhukov, born and living in Russia is Lead Engineer and Project Manager in a company which provides business software solutions. He has graduated from Moscow Institute of Physics and Technology (MIPT) (department of system programming) and has got a M.S. degree in applied physics and mathematics...

This author has published 5 articles on DotNetSlackers. View other articles or the complete profile here.

Other articles in this category

How to improve a DotNetNuke module
This article explains how to make changes to DotNetNuke modules varying their look-and-feel as well ...

You might also be interested in the following related blog posts

DotNetNuke 5.1.3 Released read more
Issue 49 - DotNetNuke 5 Skin Packaging, Spam and SQL, OWS read more
How to Install a Skin in DotNetNuke 5 - 2 Free Videos read more
Issue 48 - DotNetNuke 5 Introduction and Open Web Studio Tutorials read more
Issue 47 - DotNetNuke Nav Menu and Open Web Studio Tutorials read more
Update to Logging in to DotNetNuke from a Silverlight Application with RIA Authentication read more
DotNetNuke Tips and Tricks #12: Creating your own Authentication Provider read more
Issue 46 - DotNetNuke ASCX Skinning and Open Web Studio Tutorials read more
DotNetNuke ASCX Skinning for Professional Skinners - 6 Videos read more
Skin Exchange Contest Winners read more


Subject Author Date
placeholder Great article r m 6/28/2009 1:58 PM
Excellent article Emil Yankov 2/4/2010 7:08 AM
placeholder misunderstood reality b b 3/30/2010 3:23 AM
RE: misunderstood reality Oleg Zhukov 3/30/2010 4:21 AM
placeholder How did you... Richard Dems 7/9/2010 5:09 PM
RE: How did you... Oleg Zhukov 7/12/2010 3:47 AM
placeholder RE: RE: How did you... Sonu Kapoor 7/12/2010 9:29 AM
Very good article Patrick Smith 9/1/2010 10:01 PM
placeholder Nice artickle, but... Muhammad Sudirman 3/11/2007 4:31 AM
More about skin Muhammad Sudirman 3/13/2007 4:21 AM
placeholder Nice article B Ho 12/5/2008 12:23 PM

Please login to rate or to leave a comment.