Back to Top

Get In Touch

Our offices are located in downtown Champaign in the old Surface 51 building south of Champaign Surplus and just north of the intersection of Springfield and Neil:

309 S Neil St., Champaign, IL 61820-3169

Directions

Phone: (217) 531-2966  •   Fax: (866) 298-5499
General Inquiry: [email protected]
Support request: [email protected]

More info »

Content

DNN - Fine Tuning Your HTML Output

An approach to crafting better HTML output in DNN Platform that will make your front-end developer very happy

Saturday, July 4, 2020

Author: Accuraty / Jeremy

DNN's HTML output hasn't changed much over the years. But HTML/CSS has and a variety of best practices have come and gone. Fine-tuning very basic things are often critical, or at least greatly desired for some reason or other. Here is what DNN's "out of the box" HTML looks like:

...
<html  lang="en-US">
<head id="Head">...<title>Home</title>
...
</head>
<body id="Body">
<form method="post" action="/" id="Form" ...

I was approached by a frustrated front-end developer who was used to "decorating" this output down to the last detail, and he couldn't see any way to accomplish this in DNN. Sure enough, DNN's theme scheme (skins and containers) doesn't directly allow for getting at the things like the attributes of the HTML and BODY tags. I asked to see exactly what he wanted (needed?) and got this, additions highlighted:

...
<html class="no-js" lang="en-US">
<head id="Head">...<title>Home</title>
  ...
</head>
<body id="Body" class="site" data-component="Site">
  <form method="post" action="/" id="Form" ...

Not much difference, right? A class added to the HTML tag and more added to the BODY tag. Being a responsible manager and wondering if this was really necessary, I asked why (and in case you were wondering) these were the answers.

  1. <html class="no-js"> - is sort of best practice, an easy way to write fallback CSS to make sure critical features work if JS is busted.
  2. <body class="site" ... > - is for how we are proposing to tweak layout CSS — especially stuff that is in the theme but not included in Bootstrap. 
  3. <body ... data-component="Site"> - is for a little JS component framework we are using.

So was any of it strictly necessary? Who cares, he said the magic word, "Bootstrap." Let's get this done.

This is going to require some ASP.NET knowledge and code. We want this code to live in the right place, so we decided to keep it part of our custom theme (at Accuraty we are an agency and build most of our sites using our own custom DNN theme, you can see it here if you are interested, the code below was added to the bottom of includes/_registers.ascx).

The Solution

We need a hook into the page output getting built (we'll use Page_Init()) and for this to work, we'll need to change the default AutoEventWireup to from False to True:

<%@ Control language="C#" AutoEventWireup="true" ...

Now we can add this in our skin's ascx file:

<script runat="server">
  // Important: for this to work, AutoEventWireup (above) needs to be True
  protected void Page_Init(object sender, EventArgs e) {
    // get a pointer to the Page
    DotNetNuke.Framework.CDefault thisPage = (DotNetNuke.Framework.CDefault)this.Page;
    // see DNN's /Default.aspx; note that this could break someday, 
    // see HtmlAttributes in Default.aspx.cs
    // get a pointer to the Literal inside the <html> tag
    var litHtml = (System.Web.UI.WebControls.Literal)thisPage.FindControl("attributeList");
    litHtml.Text = "class=\"no-js\" " + litHtml.Text.Trim();
    // get a pointer to the <body> tag (control)
    var tagBody = (System.Web.UI.HtmlControls.HtmlGenericControl)thisPage.FindControl("Body");
    AppendCssClass(tagBody, "site");
    tagBody.Attributes["data-component"] = "Site";
  }
  public static void AppendCssClass(HtmlGenericControl control, string cssClass) {
      // Ensure CSS class is definied
      if (string.IsNullOrEmpty(cssClass)) return;
      // Append CSS class
      if (string.IsNullOrEmpty(control.Attributes["class"])) {
        // Set our CSS Class as only one
        control.Attributes["class"] = cssClass;
      } else {
        // Append new CSS class with space as separator
        control.Attributes["class"] += (" " + cssClass);
      }
  }
</script>

That was it. If you are used to ASP.NET, this is surprisingly readable. In English, we hook the page initialization, get a pointer to the attribute list of the HTML tag's control, and insert our new class. Then we get a pointer to the BODY tag's control and add both our new attributes. 

The results are a perfect match for what was requested. They also quickly brought half a tear to our front-end developer's eye.

Questions

Why not just edit DNN's Default.aspx?

It is actually a pretty bad idea. Yes, it works, but the very next time you upgrade DNN to the latest version, that file - and therefore your changes - will get overwritten and everything depending on your customizations will simply stop working.


Thanks: Daniel Valadas, Chris Lusk, and Will Strohl

Posted In: Technical  |  Comments (0)

Wanna hear more?

Find out more about our services, or get started on your next project.

Let's go!

quick links