Find a post...

DNN-Connect Blogs

Making DNN More Design-Centric

The roots of DNN are in Webforms. In the early days of this was Microsoft’s evolution of the Active Server Pages technology. Since then the world has moved on quite a bit. Various alternatives to Webforms have been introduced on the Winstack and by and large PHP has grown more explosively than any .net based technology. In part, because the php-based cms solutions have been kinder to web designers. How else to explain the vast amount of skins (themes) available to them and the general disdain of any web design firm for .net? OK. Maybe this is not entirely accurate, but the feeling I get is that we could make progress by making DNN more design-centric. And in my opinion that translates to: ensuring a designer has a better grip of where the HTML and CSS is coming from and where to change this.

One of the complexities, here, is that due to the plethora of coding technologies/methodologies now available to us, no module is like another. This makes it harder for anyone to tweak a complete site as one needs to “get into” a new module countless times. Another is that with our in-line editing approach (as opposed to a management interface) to pages, it is not easy to understand what is going on just by looking at a page. Even in edit or layout mode. E.g. which modules are being displayed and which containers? Or if there are any tweaks to the containers in terms of HTML/CSS. This article proposes a solution consisting of two parts: a uniform approach to templating and a management part dedicated to design.

A unified approach to templating

I’ve already written at length about a specific solution for templating in DNN modules. In this post I’d like to focus on a broader strategy for templating. A quick research on the module I’ve used on a couple of recent sites I’ve worked on shows me there are 3 places where templates are stored:

  • In one or more files on disk
  • In the resx file
  • In module settings
  • In a custom format (e.g. NBStore uses xml files)

There are several disadvantages with having various methods mixed in a single system. For one it is hard for a designer to know where physically a piece of HTML is coming from. And secondly: the editing experience tends to be very different for each. We could gain a lot by having a single mechanism prevail and become “best practice”. And that standard should be in files on disk. Why?

Well, consider the resx file solution. It is quite commonplace in DNN modules to store templates in there (even the core modules do this) and it stems from using the resource file for email templates. The resource file is most commonly used to store texts that need to be translatable. There is a “cascade” to ensure that the best match text is retrieved. You can have a resource file at portal level and at system. So you can override a text in the portal for a specific language. Very useful. But templates operate at module level. In most application areas you must be able to apply/choose a template for a module individually. Maybe multiple modules share the same template, but by choice. So the resource file as storage for your template is not a good idea as it cannot cope with all these scenarios. I can see how it’s OK for email templates, but not for display templates.

Now to the module settings approach. A number of modules, such as Events for instance, get their templates from the resource file and then store them in module settings. With this mechanism, the advantage of localization of resource files is of course lost, but what is gained is the module level control of the template. But this system not only loses localization it also loses a lot of its portability. Sure we can use DNN’s IPortable, but preparing something in staging and porting it to production becomes a big hassle.

Finally the custom solution. I’m sure there are solutions that can’t be caught in one of the other approaches. But what you lose in this situation is that you require the designer to get familiar with your way of doing things. It increases the overall complexity of the system. There is a whole cottage industry of people that know how to skin module XYZ. In itself not too bad (everyone makes a buck) but it leads to the whole platform being seen as difficult to design.

My proposal boils down to this:

  • Use a file based approach to templating
  • Given that not all templates can be caught as a single file, let’s use a folder to group one template together
  • Let’s agree on a standard way to store the templates, e.g. DesktopModules/MyCompany/MyModule/Templates/TemplateX
  • Let’s agree on a standard cascading mechanism (system, portal, etc)

Of course we will also want to ensure that they can be localized which should/will be the topic of another post. Now, what are the biggest advantages we can gain with this approach?

  • Designers will find it easier to find your templates
  • Easy to move/redistribute
  • We can make a generic template editor
  • You could roll a template into a skin
  • We can even imagine a “template exchange”
  • A better template management

I’ll elaborate on a number of these.

A generic template editor

One thing that has bugged me is that as attractive as the use of templates is, it’s a drag to have to implement an editor in your module. It’s a lot of work and if you’ve done it twice you keep thinking to yourself: this should be centralized. And because the template editor is not necessarily “core functionality” of a module, it ends up being the “not so pretty part” of the application. It doesn’t get a lot of love. Most modules just implement a straightforward textbox on the main settings screen or rely on the core’s resource editor.

So how about centralizing that? How about a “core” template editor that can be leveraged by modules and the designer to edit the templates? The editor would be primed with just a path to the template folder and would be able to edit any file underneath this. And we could then make a really decent editor. I’m thinking of using the Codemirror library, for instance. This is used in the new SQL module if you want to see what that’s like. And we could define a standard for the module to communicate to the designer what is allowed and what isn’t. Specifically: the tokens and what they mean. The editor could then display these neatly alongside the editor. If done consistently by modules, then editors will get a consistent editing experience, making working with DNN a joy!

Templates as part of a skin

I’ve recently implemented this for the Blog module. The possible places where templates can be stored for the Blog module are:

  • In the module directory (i.e. DesktopModules/Blog/Templates)
  • In the portal directory (Portals/0/Blog/Templates)
  • In the skin directory ({templateDirectory}/Templates/Blog)

Now this is not yet perfect. I’d like to add host level templates (so under Portals/_default) and we need to unify the path naming (so in all cases Templates/MyCompany/MyModule). But the important take-away, here, is that a designer could group all the work in the skin folder and redistribute that as a complete package that skins not just DNN, but also individual modules. That is a huge win, IMO.

A template exchange

Like skins, templates can be a lot of work to do nicely. So why not allow people to share their work. One of the ideas I’ve had for future development for the Blog module is to have some sort of central template repository where users can exchange their templates. Naturally, if we have a unified approach to templating we could make a more generic exchange.

Template management

The template editor, then, should be able to manage the templates. I.e. upload, download, and copy. With copying, you’d have the opportunity to copy a template from a distributed level (in the module directory for instance) to the portal level.

Baby steps

The first thing I need to do is to create the generic editor to show you the power of this idea. Rome wasn’t built in a day and for sure we’re not going to have all module immediately follow this pattern unless it is clear that the tooling is there and that there is a real advantage. Anyone is welcome to join this effort with me.


Error: Object reference not set to an instance of an object.

In: at DotNetNuke.Modules.Blog.Templating.LazyLoadingUser.GetProperty(String strPropertyName, String strFormat, CultureInfo formatProvider, UserInfo AccessingUser, Scope AccessLevel, Boolean& PropertyNotFound) at DotNetNuke.Modules.Blog.Templating.BaseCustomTokenReplace.replacedTokenValue(String strObjectName, String strPropertyName, String strFormat) at DotNetNuke.Modules.Blog.Templating.BaseTokenReplace.ReplaceTokenMatch(Match m) at System.Text.RegularExpressions.RegexReplacement.Replace(MatchEvaluator evaluator, Regex regex, String input, Int32 count, Int32 startat) at System.Text.RegularExpressions.Regex.Replace(String input, MatchEvaluator evaluator) at DotNetNuke.Modules.Blog.Templating.BaseTokenReplace.ReplaceTokens(String strSourceText) at DotNetNuke.Modules.Blog.Templating.GenericTokenReplace.ReplaceTokens(String strSourceText) at DotNetNuke.Modules.Blog.Templating.Template.ReplaceContents()

Geoff Barlow
  I think this a great idea. I think the option of placing all templates in the portal folder ('Portals/0/Blog/Templates') would be the best idea. For example, if in the future there is functionality to export a single portal (which I think we all would like to see) all templates used by the portal would be exported easily. Maybe it would be an idea to have a central toolkit available for module developers which would include the editor for templates + css and token replace solution that you have blogged about for example. Another idea would be to have these 'module helpers'/toolkit incorporated in in Chris Hammond's Christoc's Dnn Mod Dev Template or to create a new dev template with the toolkit.
· reply · 1 0 0
Torsten Weggen
  Hi Peter, sent you a mail explaining my solution for this (was to hard to fill in the comment box)
· reply · 0 0 0
Sebastian Leupold
Sebastian Leupold  Sorry, Peter, but I have to disagree. While a bunch of small files look nice in the first place and has the benefit of easy transportation, there is a lack of flexibility and integrity for more complex scenarios. If you consider a list, it is easy to provide a template for Header, Footer, Item and maybe alternate item as individual files. however, this require the hosting module to provide the control structure, i.e. sequence Header {+ Item + AlternateItem} + Footer. However, as soon as the developer decides to add a separator template as well and chooses a non-empty default, the approach fails. Same applies to hierarchical situations (client with bills, each with items on it). Shouldn't the site owner decide, whether he displays a list with or without child items? Unfortunately, the only convincing approach I have seen so far, is XSL - Stephan did a great job in FnL module. AND, he also took the first step into the right direction: hiding the generation defaults from the public by using a generator - IMHO the best generator for the masses would be a visual designer. This might not produce the best code and there are designers keen on optimizing it, but it would combine flexibility, power and easy of use. Whether the result is stored locally in a file or the database (per language), is just a minor details - though for module instances, I'd prefer a database approach, e.g. using TabModuleSettings, which get automatically cleared, when the module is deleted and purged from the recycle bin.
· reply · 0 0 0
Sacha Trauwaen
Sacha Trauwaen  @Peter Nice summary of what will really help the platform grown. @Sebastian You are right, templates don't fit in high speed evoluating modules. And sure a abstraction layer with a generator can be a solution. Think about the skins of dnn in html or ascx format with skinobject witch is a flexible extension point of the skin templating system. This solution has also a nice advantage it’s compiled to .net class with performance gain. This is also the case for Razor templates. The concept of the 2 level templating (html / ascx or html / razor) is interesting, with a generator from high lever to the low level template language. @Sebastian I think also you are right, that a template designer (ide) is a must for complex templates. Which you have for free, when you create razor templates in visual studio (syntax highlighter, code insight, warnings, error, …). At last, templates are coupled with tokens. If you make a centralized template admin module, you have to make also a centralized token admin module.
· reply · 0 0 0
Daniel Mettler
Daniel Mettler  Thanks for the summary of a large, common issue. I would like to add 3 important notes: 1. Actually the template-language wasn't addressed. This is crucial, because right now every system uses another language, making it very hard for designers. Form & List uses XSLT, NBStore uses XSL, Many tools use Tokens, 2SexyContent uses Tokens & Razor. I personally believe the tokens/razor is the only way to go. 2. The Desktop-Modules is a real mistake - for most needs. Because if you have a 1-portal installation (the most stable and nice, etc.) then it doesn't matter where it is. If you have a bunch of common portals than /portals/_default works, and if you have a mix of very different portals, each portal should have their own. So I really recommend eliminating the templating inside desktopmodules. It gets killed on updates and more - we from 2sic (who daily need to correct the output) really, really hate it. 3. CSS-Frameworks. If people would adhere to certain conventions, the design-work would be much, much easier, irrelevant of the templating used. BTW: I claim that 90% of modules which require extensive skinning have very little custom logic - they are usually "presentation" components for data in the backend. This is why 2SexyContent is structured to automatically handle the entire backend, and focus on designed output. If people would volunteer to help with the EAV and add data-pipelines to other tools, everything could be skinned (and output-configured & translated...) in 2SexyContent.
· reply · 1 0 0
Daniel Mettler
Daniel Mettler  Line-breaks suck in this tool :(
· reply · 0 0 0
DNN-Connect 431 6
Peter Donker 5141 30
Declan Ward 547 1