The Seven Sins of DotNetNuke Module Developers
In an average week, I communicate on the phone, by email, through webinars and in person, with some 100 DotNetNuke business customers, prospects and partners. A majority of them use DotNetNuke in some mission-critical way. I enjoy these conversations and get many insights on their real-world experience with DotNetNuke. I have noticed that there are some common things that end-users find problematic with Core and/or third-party extensions they use with DotNetNuke. It occurred to me that it would be good to share this information since not all extension builders may be aware of the issues that sometimes arise due to the way a particular extension is built. In order to make the information easy to digest (and because lists are cool), I am going to present these observations using a “Seven Sins…” theme.
Let’s start with the Seven Sins of DotNetNuke Module Developers:
Sin: Using inline style attrbutes in your HTML markup is probably the single, biggest problem you can create for your end-users. Since such attributes cannot be overridden with CSS, users are forced to edit the markup, use Javascript or the StyleScrubber Widget to neutralize the impact of a module’s inline style attribute on other elements of a page.
Sin Level: Annoyance
Absolution: Avoid using in-line style attributes in your module’s static and dynamic HTML markup. Instead, create style definitions in your module.css file that target your module’s markup. While you can use “class” and “ID” attributes throughout your markup, it is best to keep your markup clean and use the various CSS selectors to achieve the desired styles. An approach that works well is to create a “wrapper” DIV for your module’s markup with a “class” attribute value that closely matches your module name (for example: <div class=”Acme-Survey-Module”>). You can then have styles in your module.css like this:
.Acme-Survey-Module div { padding-bottom: 10px; }
And since we are on the topic of style-related sins, please do not specify any font-related style attributes in your style definitions. Let the page skin’s font definitions rule. If you absolutely must change the text size, at least use “em” units instead of pixel or point units so that the text size is relative instead of absolute.
Sin: Assuming that user input is safe and processing or persisting it without filtering, potentially compromising security and making a user’s DotNetNuke installation, server and network vulnerable to attacks.
Sin Level: Deadly
Absolution: DotNetNuke has built-in features, including an input filter that is incredibly easy to use for filtering strings. Use it to filter user input and make your modules more secure.
Sin: Hard-coding user interface text in HTML markup or in code, preventing localization and customization of text.
Sin Level: Aggravating
Absolution: Do not assume that everyone speaks the same language as you, and even if so, that they like the error prompt “Yo…you messed-up, fix it already.” Ensure that all user interface text follows well-established best-practices for DotNetNuke Localization.
Sin: Using an UpdatePanel instead of writing the code necessary to properly implement AJAX functionality. If your module is doing something trivial, by all means, use UpdatePanel. But for a module that is potentially going to be used in high-traffic scenarios, UpdatePanel is a no-go. UpdatePanel was intended to be a quick and easy way to implement AJAX functionality — it would not be a stretch to call the UpdatePanel solution LAJAX (lazy AJAX). Unfortunately, it has become the standard way in which most ASP.NET developers implement AJAX functionality. For every AJAX request, UpdatePanel causes the entire page life-cycle to be repeated on the server. As a result, a module that has lots of AJAX functionality implemented using UpdatePanel is going to cause significant performance issues and unnecessary resource utilization when used in a high-traffic environment.
Sin Level: Aggravating
Absolution: As I mentioned, if your module is doing something trivial, UpdatePanel is a reasonable solution. For anything else, it’s better to use ASP.NET AJAX or jQuery on the client-side making requests to an HttpHandler or Webservice to obtain the needed information for the UI in JSON or XML format. Here’s an example of how this can be done in a DotNetNuke module.
Sin: Using HTML markup for layout, instead of CSS, provides no semantic cues to user agents (browsers) as to the intended purpose of content. Most online discussions about semantic HTML markup degrade very quickly into near-religious arguments about TABLE versus DIV element. Such discussions are akin to throwing the baby out with the bath-water. Semantic markup is not solely about using tables for layout. The bigger issue is that HTML was never intended to convey presentation fidelity to the degree seen on modern web pages. Its primary purpose was to give semantic meaning to text so that user agents could then render the text in the most appropriate way for that agent. When markup is created with an emphasis on layout, it strays from this purpose. For instance, if your module markup uses an H1 element for content that is not the primary headline on the page, your markup is non-semantic and is misguiding user agents such as screen readers.
Sin Level: Annoyance
Absolution: I don’t view the issue of semantic HTML markup as a black-and-white one. I think it’s OK to take occasional liberties with markup to save time, after all time is money. But every developer should make a good-faith attempt to produce more semantic markup. Take a look at your module code and see if there are opportunities to replace HTML markup used for layout with CSS (without giving yourself a case of DIVitis). Low hanging fruit includes H*, B and I tags and input forms. For forms, try ditching the all-too-common TABLE found in most DotNetNuke module forms and replacing it with the FIELDSET element along with some CSS. For a good example of this, refer to the DotNetNuke Blueprint project.
Sin: Using a custom, non-standard user interface for managing module settings.
Sin Level: Aggravating
Absolution: DotNetNuke provides a simple and automatic mechanism for module developers to implement a user interface for managing module settings. Developers should not circumvent it as it adversely impacts usability of the platform. It takes time for users to get familiar and comfortable with standard behaviors. Each time a user encounters a module that ignores the standard and does something custom with the user interface, it causes the user to get frustrated with the platform (i.e. DotNetNuke). This is because, contextually, he/she has no knowledge of the separation between the platform and the module. As far as the user is concerned, DotNetNuke appears to have an inconsistent user interface (which it well might, but that’s another discussion). Why force the user to click on a custom link or button to configure your module’s settings? Let the framework do its thing and inject your settings control at the end of the standard module settings so that the user can customize module settings in the same way, no matter which module they are using.
Sin: Using “dbo” in module SQL scripts instead of {objectQualifier} and {databaseOwner}. If your module SQL scripts use “dbo” for the object owner your module cannot be easily installed in environments where the SQL connection uses a different database owner. If your module SQL scripts do not use the {objectQualifier} prefix for database objects, your module cannot be used in shared database scenarios.
Sin Level: Aggravating
Absolution: Follow DotNetNuke best practices for SQL scripts by using {objectQualifier} and {databaseOwner} prefixes in your module’s SQL scripts to ensure that your module can be installed in any environment where DotNetNuke is able to function.
There you have it…the seven sins of DotNetNuke module developers. What other cringe-worthy things have you seen in DotNetNuke modules?
Next up, the seven sins of DotNetNuke Skin Designers.
Han
Very helpful blog! Thanks, Nik. Look forward to the next one.
wmorgenweck
Excellent post Nik. I would have to suggest that there are exceptions to the Custom Settings rule. While the current module settings is a standard, it is far from user friendly. In our latest release of Active Social we introduced a modal window that is opened from the module actions and provides one click, very quick access to our basic module settings. We also make our settings immediately available when you first add the module to the page. In most cases this saves some extra clicks too.
I would say another sin would be including third-party components with the module that aren't packaged properly. Even worse is when the components are not licensed properly.
uberVU - social comments
Social comments and analytics for this post... This post was mentioned on Twitter by techbubble: Blogged: The Seven Sins of DotNetNuke Module Developers http://bit.ly/9dssxw...
Rodney Joyce
Great post as always Nik - thanks for sharing... guilty of a few sins myself..
Bruce Chapman
This is very important information for module developers out there. I would also add that, while it is tempting to skip over these for 'quick and dirty' applications - quick and dirty applications have a funny tendency of living for a long time, and causing problems down the track from the shortcuts.
Thankfully I'm (mostly) free of these sins, though at times I've been known to fall into the UpdatePanel trap, only to regret it later on. I have seen some truly shocking implementations of the UpdatePanel though.
Paul Bolejack
Thanks. Although there is a lot of information out there to help one learn DNN, there's not much in the way of best practices. This helps pull some of that together.
With respect to sin #1... the inline width styles coming out of the core admin modules can be really annoying.
Aderson Oliveira
Where, in the realm of DNN sins, would you put "Using Wordpress instead of DotNetNuke for a blog" ;)
Jokes aside, very good post and I will be seeking redemption from this list from now on. I will use it as a check list for sure
techbubble
It's a fair comment. I like to use the most suitable tool for a task with the least bit of overhead. In this case, my only need was for a blog -- I did not need membership, adding other application functionality, enabling others to post content, etc. I evaluated various blog solutions, hosted and on-premise. I wanted something that would run with minimal fuss on Amazon EC2. I settled for WP on-premise as it was quick and easy to setup via the Web Platform Installer and other than a periodic "white screen of death," it has served well.
Aderson Oliveira
I do understand your point of view and I agree. I debated with myself quite a lot before deciding to use DNN for blogging instead of Wordpress. But I did that not because DNN would be the best option for the task in hand, but because it would be a bit strange that I would be posting videos about DNN but using another platform.
Please don't take it as a criticism. I was just picking on you. :)
Adrian
Excellent post. I plan to forward this to my web developer who is not necessarily one to commit such sins, but has inherited some code that most definitely has! This would serve as a good "heads up" to any outsourced developers I may use also, as the start of a specification document ...
I now look forward to reading the Sins of DNN Skin Designers, which lands fairly and squarely in my lap
Dnnguy
I would say this apply to normal asp .net application except one or two point, it is not specifically for DNN.
Brook Little
Howdy, Are you going to be posting a follow-up article? My partner and myself have squandered some time checking over your web-site and funnily enough you highlighted some thing i was referring to only the other day with our son's football coach. We often hear ourselves arguing about the smallest of issues, isn't it childish?
Ian Hsieh
I have a the same feeling about the first sin. The developer of the blog module that comes with DNN uses crazy lots inline styles while CSS class is right there. I cannot understand his logic for using the CSS class in module.css and the inline styling to override all those CSS styling.