DotNetNuke Admin Pages

DotNetNuke divides the admin pages for a website into two sections:  common settings and advanced settings.

To view the admin options hover over the

Section Common Settings covers:

Section Advanced Settings covers …

DotNetNuke Admin Themes

The DotNetNuke admin themes page shows the skins and containers available for use by the website.

The page is dividend into 4 sections:

  • Theme editor
  • Themes
  • Containers
  • Edit Theme Attributes

Theme editor

Use the dropdown lists and checkboxes to restrict the themes and containers listed.

Whilst reviewing the page I found that older themes were showing the message: This is a Legacy Theme. Although the entries are still apearing in the lists.

Themes

The themes available for use on the website are shown, with an image preview. For each there’s the option to preview what the site will look like with the chosen the theme. And alongside a button to apply the chosen theme.

Below the container list are two buttons to Parse Theme Package and Restore Default Theme.

Take care choosing to parse the theme package. Its looking at the original configuration. The results may be helpful if things aren’t working but can revert changes.

Containers

Like the themes, the available containers are shown as images, with buttons for preview and apply.

Edit Theme Attributes

I’ve never used the attributes editing option, preferring to edit the relevant files directly. However, its does present a convenient way to make changes to the appropriate components of a theme or container.

For example if the breadcrumb is in use then the separator can be easily changed simply by selecting the file, the Breadcrumb token the separator setting and adding a new value. An example might be changing from the pipe symbol “|” to a greater than sign “>”.

DotNetNuke Admin Device Preview Management

On the Admin Device Preview Management page there are a number of pre-defined mobile devices, tablets and phones.

Above the list of mobile devices there are:

  • A combo box (to add a new name, or select an existing device)
  • 3 text boxes to specify the browser size and agent details.

Create and review the mobile device options.

The mobile devices which have been added are used in the mobile preview.

To view the mobile version of a page, click on edit page, in the top right corner, and from the drop down list select Mobile Preview. A pop-up will then show with the devices listed and their orientation details. Make your selection from the configured list.

Alternatively – rather than configure individual devices, why not configure the typical responsive device sizing and orientations?

Admin Advanced Pages

Further pages in the admin common settings section are given in the table below:

Advanced Configuration SettingsDevice Preview ManagementExtensionsGoogle Analytics
LanguagesListsNewslettersSearch Engine Site Map
Site LogSite Redirection ManagementSite wizardSkins
TaxonomyVendors  

DotNetNuke Admin Search Admin

The DotNetNuke Search Admin page is for the management of the internal search indexing, not for search engines such as Google, Baidu, and Bing.

I have found that over time some entries within the search index are old, having lost their prior page content reference.

The search admin page can be used to refresh the references held, ensuring that the content is relevant to searches.

You may wish to consider the items listed under the Ignore Words tab. Adding items here can reduce the number of entries retained in the search index, reducing the size of the database tables and increasing the speed of the website, both in terms of searching and general performance.

If re-indexing the content , on the General tab view, doesn’t flush the old content, or more significantly it times out, this can be an indication that the tables have become too large. You may wish to consider an alternative method for emptying the search tables.

CustomValidator with Client JavaScript

I had crafted a custom validator for an DNN asp.net web page with a function to validate form elements.

Using the DNN pop-up calendar, with appropriate date formatting according to the browser, had issues with visitors not setting the language within the browser correctly. It was also decided that using 3 dropdownlists would provide a better control of the selection, and less issue with date selection on mobile devices using the pop up calendar.

I added 3 drop down lists to a web page to facilitate date selection.

To ensure that the date was valid I created a custom control to be referenced on the page with validateDate()

Initially I found that the function was firing, but that the status wasn’t being returned.

The JavaScript function was amended, requiring both sender and args parameters, like so:

<script type="text/javascript">
function validateDate(sender,args) {
    var ddlDay = $("#<% = ddlTheDay.clientid %>");
    var ddlMonth = $("#<% = ddlTheMonth.clientid %>");
    var ddlYear = $("#<% = ddlTheYear.clientid %>");

    document.getElementById('<% = cvTheDay.clientid %>').style.display = 'none';
    document.getElementById('<% = cvTheMonth.clientid %>').style.display = 'none';
    document.getElementById('<% = cvTheYear.clientid %>').style.display = 'none';

    // check date was selected
    if (ddlDay.val() < 0 ||
        ddlMonth.val() < 0 ||
        ddlYear.val() < 0) { // if ($('.validateDate').hasClass('validDate')){ // $('.validateDate').toggleClass('inValidDate validDate'); //} args.IsValid = false; return false; } // ensure days value correct if (ddlDay.val() > daysInMonth(ddlMonth.val(), ddlYear.val())) {
        args.IsValid = false;
        return false;
    }


    // check date is valid
    var dobDate = new Date(ddlYear.val(), ddlMonth.val() - 1, ddlDay.val());

    if (Object.prototype.toString.call(dobDate) === "[object Date]") {
        if (isNaN(dobDate.getTime())) {
            // date is not valid
            args.IsValid = false;
            return false;
        }
        else {
            // date is valid
            args.IsValid = true;
            return true;
        }
    }
    else {
        // not a date
        args.IsValid = false;
        return false;
    }
}

function daysInMonth(month, year) {
    return new Date(year, month, 0).getDate();
}
</script>

Shown below are the dropdownlists, together with their custom validators.

<asp:dropdownlist id="ddlTheDay" visible="true" runat="server" name="ddlTheDay" class="ddlTheDay" />
<asp:dropdownlist id="ddlTheMonth" visible="true" runat="server" name="ddlTheMonth" class="ddlTheMonth" />
<asp:dropdownlist id="ddlTheYear" visible="true" runat="server" name="ddlTheYear" class="ddlTheYear" />
<asp:customvalidator id="cvTheDay" runat="server" SetFocusOnError="True"
Display="Dynamic" ErrorMessage="The date is invalid!" ControlToValidate="ddlTheDay" ClientValidationFunction="validateDate" />
<asp:customvalidator id="cvTheMonth" runat="server" SetFocusOnError="True"
Display="Dynamic" ErrorMessage="The date is invalid!" ControlToValidate="ddlTheMonth" ClientValidationFunction="validateDate" />
<asp:customvalidator id="cvTheYear" runat="server" SetFocusOnError="True"
Display="Dynamic" ErrorMessage="The date is invalid!" ControlToValidate="ddlTheYear" ClientValidationFunction="validateDate" />
<div class="validateDate validDate">The date is invalid!</div>

As can be seen above I am using just the one div with the error announcement. Its default setting is within the module’s CSS file module.css, details are below:

.validateDate{color:#d00;font-weight:bold;}
.validDate{display:none;}
.invalidDate{display:block;}

A RadioButtonList in a GridView

A GridView is to include a RadioButtonList in its presentation. The options are to be populated as fixed options, not taken from a database.

The example below takes values from the DotNetNuke Lists and displays them as a radio button list.

In the presentation file there is a GridView, called gdvMembership

<asp:GridView ID="gdvMembership" runat="server"
  AllowPaging="false"
  AllowSorting="false"
  AutoGenerateColumns="false"
  GridLines="none"
  cellspacing="1"
  border="0"
>
  <Columns>
    <asp:TemplateField ItemStyle-HorizontalAlign="left" ItemStyle-Width="80%">
    <ItemTemplate>
    <asp:RadioButton ID="rbnOptions" runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.Text")  %>' GroupName='<%# DataBinder.Eval(Container, "DataItem.Value")  %>' Checked='<%# DataBinder.Eval(Container, "DataItem.Selected")  %>' AutoPostBack="true" OnCheckedChanged="setSelection" />
    </ItemTemplate>
    </asp:TemplateField>
  </Columns>
</asp:GridView>

In the code behind, a subroutine is used to populate the GridView and to set the selected item.

Private Sub Registration(ByVal SeclectedValue as string)
  Dim dt as DataTable = new DataTable
  dt.Columns.Add(New DataColumn("Text"))
  dt.Columns.Add(New DataColumn("Value"))
  dt.Columns.Add(New DataColumn("Enabled"))
  Dim row as dataRowrow = dt.newRow()
  row("Text") = "I am registered with the organisation"
  row("Value") = "Registered"
  row("Enabled") = True"
  If SelectedValue Is Nothing Then
    row("Selected") = False
  ElseIf SelectedValue = "Registered" Then
    row("Selected") = True
  Else
    row("Selected") = False
  End If
  dt.Rows.Add(row)row = dt.newRow()
  gdvMembership.DataSource = dt
  gdvMembership.DataBind()
End Sub

Whilst populating the rest of the page content the above sub-routine is called with the value of the registration status.

Registration(objIApplication.Membership)

Radio buttons of a different row in a GridView cannot be grouped together. The issue is caused by each row in the GridView being given a different ident.

The radiobuttons are therefore not of the same name once the page is rendered.

<input id=”dnn_ctr485_application_gdvMembership_rbnOptions_0″ name=”dnn_ctr485_application_gdvMembership_rbnOptions_1″…>

Use the GroupName parameter.

I had considered using JQuery to change uncheck the other options when the selection is changed. However, I chose to use an auto postback and a call to a function: don’t forget to add AutoPostBack=”true”.

Protected Sub setSelection(ByVal sender As Object, ByVal e As System.EventArgs)
  For Each row As GridViewRow In gdvMembership.Rows
    Dim rb As RadioButton = TryCast(row.FindControl("rbnCUOptions"), RadioButton)
    Dim rbn As RadioButton = TryCast(sender, RadioButton)
    If Not rb Is rbn Then
      rb.Checked = False
    End If
  Next
End Sub

Empty the DNN Site Log

An excessively large SiteLog table is likely to have an impact on the performance of your website. Do you know how many entries there are and whether the older ones are being cleaned out?

I have found that the DNN Site log table can be prone to growing, unrestricted.

This can be brought about by the failure to set a day limit and not enabling the scheduled clean up task.

In the past I have found values in the site log which precede the given cut-off date. Often as a result of the number of days being reduced, but the SiteLog purge not running properly.

Maybe looking through the scheduled task notifications you are seeing messages which show the purge of the site log is failing.

Failure of the scheduled task to run is often a sign of a table which has grown too large and is timing out on the deletion.

Information about the site log table SiteLog can be gained via the admin SQL Console.

Empty the DNN site log: count number of rows

SQL is entered within the main text area and run by clicking on Run Script.

Take care! It is easy for an entered command to wipe table contents, beyond the intended results.

The size of the table, ie. the numbers of rows in the table, can be determined by running the command:

SELECT count(*) FROM SiteLog

It’s also possible to see if there are entries earlier than your set limits.

This can be done by running the command

SELECT TOP 10 * FROM SiteLog ORDER BY DateTime DESC

Shown below a typical set of results, based upon a newly enabled sitelog, with the number of columns abbreviated for clarity.

DateTimeReferrerUrlUserAgent
21/03/2018 12:32:00http://localhost/Admin/Site-Settingshttp://localhost/Default.aspx?TabId=67&language=en-GBMozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
21/03/2018 12:32:00http://localhost/http://localhost/Default.aspx?TabId=56&language=en-GBMozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
21/03/2018 12:33:00http://localhost/Admin/Site-Settingshttp://localhost/Default.aspx?TabId=67&language=en-GBMozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
21/03/2018 12:33:00http://localhost/Admin/Log-Viewerhttp://localhost/Default.aspx?TabId=21&portalid=0&language=en-GBMozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
21/03/2018 12:33:00http://localhost/http://localhost/Default.aspx?TabId=56&language=en-GBMozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36

If there are entries preceding the cut-off date these may be deleted using

DELETE FROM SiteLog WHERE DateTime < given date

Dates are awkward to deal with. By default entries are stored in American date format. It is also anticipated that dates used will also be in this format too. Rather than adding formatting information when running these commands you may wish to simply accept the default format.

To ensure that you are going to delete the correct items try a selection first, based upon your date range

SELECT * FROM SiteLog WHERE DateTime < CONVERT(DATETIME, ’03/21/2018′)

From my example above I am expecting this to return no results, which is the case.

Whilst setting the date as 22/03/2018 gives:

DateTimeReferrerUrlUserAgent
21/03/2018 12:32:00http://localhost/Admin/Site-Settingshttp://localhost/Default.aspx?TabId=67&language=en-GBMozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
21/03/2018 12:32:00http://localhost/http://localhost/Default.aspx?TabId=56&language=en-GBMozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
21/03/2018 12:33:00http://localhost/Admin/Site-Settingshttp://localhost/Default.aspx?TabId=67&language=en-GBMozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
21/03/2018 12:33:00http://localhost/Admin/Log-Viewerhttp://localhost/Default.aspx?TabId=21&portalid=0&language=en-GBMozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
21/03/2018 12:33:00http://localhost/http://localhost/Default.aspx?TabId=56&language=en-GBMozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36

You may also wish to sort by the datetime field descending, just to get the newer entries

SELECT TOP 20 * FROM SiteLog WHERE DateTime < CONVERT(DATETIME, ’03/21/2018′) ORDER BY DateTime DESC

It’s possible with too many entries in the SiteLog that the deletion of a range of rows will timeout.

You may wish to purge the SiteLog table. I have found that doing this via the DNN SQL control console can lead to time outs and failure to action.

If the truncation of the table times out or fails then you may find that it’s Better to perform the action via the SQL Server Management Studio, if this is available to you .

I navigate to the required database table view and click on the New Query button.

Enter the following

TRUNCATE TABLE SiteLog

Refresh your table view to see the change in the number of records.

DotNetNuke can require a restart of the application to reflect changes made to the database.

With DNN 9 the site log has been removed. Although it can be added back in if you wish.

Reviewing an older site I observed that the site log still existed.

Without the original admin configuration, it’s not possible to empty the log table by following the older practices to restrict the number of days or to turn off the site log.

I chose to use the SQL truncation detailed above to empty the site log table.

References

A Site Log module: https://github.com/DNNCommunity/Dnn.SiteLog

DNN Browser Compatibility

Older versions of DotNetNuke supported the configuration of the browser compatibility of a website through the file

/js/ClientAPICaps.config

The operation of the default DotNetNuke SolPart menu with regard to different browsers is governed by this file.

The file is divided into a number of sections, for example:

<functionality nm="DHTML" desc="Dynamic HTML">
  <supports>
    <browser nm="IE" minversion="4" />
    <browser nm="FireFox" minversion="1" />
    <browser nm="Netscape" minversion="5" />
    <browser nm="Gecko" minversion="1" />
    <browser nm="Opera" minversion="7" />
    <browser contains="Iceweasel" />
    <browser contains="Konqueror" />
    <browser contains="Safari" />
    <browser contains="Camino" />
  </supports>
  <excludes>
  </excludes>
</functionality>

In the example given above I have added support for the Konqueror and Iceweasel browsers.

I created an HTML file with the following content to get the details of the browser.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
  <title>Untitled Page</title>
</head>
<body>
  <script>alert(navigator.userAgent.toLowerCase());</script>
</body>
</html>

I experimented with the browser compatibility options. As mentioned above, adding references for support of lesser used browsers. But found that realistically it added an additional complication to preparing a website. And with websites continually evolving it was going to be an overhead to maintaining websites. After my experimentation I no longer edited the browser configuration, leaving the file as is.

Whilst writing and updating the content of this article I was curious to see whether the file was still included, and if so what it contained. Looking at the latest version on GitHub I found that its content was similar:

<?xml version="1.0" encoding="utf-8" ?>
<capabilities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <functionality nm="DHTML" desc="Dynamic HTML">
    <supports>
      <browser nm="IE" minversion="4" />
      <browser nm="FireFox" minversion="1" />
      <browser nm="Netscape" minversion="5" />
      <browser nm="Gecko" minversion="1" />
      <browser nm="Opera" minversion="7" />
      <browser nm="Mozilla" minversion="1" />
      <browser contains="Konqueror" />
      <browser contains="Safari" />
      <browser contains="Camino" />
      <browser contains="Mozilla" />
    </supports>
    <excludes>
    </excludes>
  </functionality>

Not much has changed with the start of this file over the years.

DNN 9 Where’s the Allowable File Extensions?

Is the Allowable File Extensions in DNN 9 missing or simply hidden?

The good news is that it’s still available.

The Allowable File Extensions is a list of those file types configured by their file extension which are permitted to be uploaded to the website.

It’s given as a comma separated list within the site’s admin configuration.

Previously it was to be found under the Host > Site Settings page.

DNN 9 Wheres the allowable file extensions? old config option

Looking under the site configuration in DNN 9 I was unable to see the Allowable File Extensions configuration textbox.

It’s still there, but now moved under the Security option.

Begin by selecting the Security menu from the options on the left black panel

DNN 9 Wheres the allowable file extensions? Select security menu

On the security menu select the more tab at the right hand end. Opening this section.

DNN 9 Wheres the allowable file extensions? Security menu

On this tab we have the options for SSL Settings and still More Security Settings. This is the one which we are interested in. Click on it.

DNN 9 Wheres the allowable file extensions? More security settings

Finally we have the page which we are interested in, More Security Settings.

DNN 9 Wheres the allowable file extensions? Security menu more tab

Scroll down the page to the last textbox which shows a list of the different file types which are supported. Add or remove to suit your website requirements.

The Allowable File Extensions isn’t lost/missing. It has been moved under the Security menu section.

The Remote Certificate is Invalid

Configuring the SMTP settings on a DotNetNuke website gave the error, remote certificate is invalid, from the mail server:

There has been an error trying to send the test email. The error is:
The remote certificate is invalid according to the validation procedure

I often find that errors on a DotNetNuke website are logged with further information in the Event Log. To view this navigate to Admin/Event Viewer, from the top navigation bar.

Dependant upon how many messages are created on your website, for example users logging in, the error message which you are looking for may be on the second or third page. If necessary take a note of the time and force the error again, to get it on the first page.

In the Event Viewer log the gist of the error message was:

There has been an error trying to send the test email. The error is:
The message was not delivered to the following address(es) –

I found error relay not permitted.

Where the SMTP host settings for the DotNetNuke installation is configured to use a defined mailbox if choosing to use a secure connection the domain name of the certificate and mail account needs to be the same domain as that configured in the settings.

The error may be resolved by either using a mailbox with the correct domain certificate. or by using an unsecured mailbox and unticking the SSL option.