By: Timo Breumelhof
In DotNetNuke 6.1, the remove CSS functionality of our StyleHelper Skin Object stopped working.
In this blog post I'll explain why and the solution.
In short, in DNN 6.1 you can remove all stylesheets by passing all style sheets with; RemoveCssFile="/".
The issue explained:
The Client Resource Management introduced in DNN 6.1 allows combining CSS and JS files into one file and compressing them, this a great new functionality, but it does break unloading style sheets with our skin object.
To make combining style-sheets possible the way they are loaded has changed completely in DotNetNuke 6.1.
This is the reason why unloading style sheets with our Stylehelper skin object does not work the way it did any more.
Why unloading style sheets stopped working
In previous versions of DotNetNuke all style sheets were loaded if the corresponding control loaded. So as soon as a module loaded it's style sheet was injected, same for the skin and skin.css.
In Dotnetnuke 6.1 this had to be changed as the style sheets should first be collected and then combined at the end. For that the moment the style sheets are actually injected has changed.
They are now injected at the end of the page render process.
Unfortunately this is after the code of the style helper skin object is executed.
So there is no way to remove individual style sheets any more with the code executed by the Style Helper skin object as they are not injected yet when it executes.
Solutions for unloading style sheets?
In DotNetNuke 6 there are 2 new controls in Default.aspx, that are used to inject the Style sheets and Java-scripts.
<asp:PlaceHolder runat="server" ID="ClientDependencyHeadCss"></asp:PlaceHolder>
<asp:PlaceHolder runat="server" ID="ClientDependencyHeadJs"></asp:PlaceHolder>
In essence DotNetNuke first collects all the Stylesheets and then at the end injects them in the ClientDependencyHeadCss control, even if you don't switch style-sheet combination / compression on.
When the Stylehelper code runs this control is empty, the only option I have at that moment is to disable the ClientDependencyHeadCss control, which "unloads" all style-sheets.
So what are the options?
A. Use an HTTP Module
With an HTTP module (no relation with a DNN Module) I could access the generated HTML and make changes just before the result is sent to the client.
Although this seems nice, it has issues to.
It would prevent you from using the style sheet combining & compression in DNN 6.1 as at that moment in time the combined style sheet is already injected.
As that's one of the best enhancements of DNN 6.1, I don't see this as a valid solution.
B. Create our own Client Resource Management provider
The new Client Resource Management is provider based, so in principle I could create a 40Fingers version and overwrite the default behavior.
The disadvantage is that I would have to keep up with all new functionality added to the DNN version.
C. Add removing stylesheets to the Core Client Resource Management
I discussed this with Ian Robinson and he agreed it would be good if the CRM would allow unloading.
In fact he had already created an issue for this: http://support.dotnetnuke.com/issue/ViewIssue.aspx?id=19024&PROJID=2
I think it would not be smart to create a new provider at this time as there are plans to correct this in the core.
BTW AFAIK, Ian is not the one to decide if this change is going to be made.
So don't blame him it this is not changed (blame me for not lobbying enough ;-)
A. I'm going to lobby for adding unloading resources to the CRM in the core.
If the change is incorporated I'll add support to the style helper skin object.
If the change is rejected I'll consider creating a spin-off of the provider.
B. I changed version 02.04.00 so now even in DNN 6.1+ you can removes all style sheets with; RemoveCssFile="/".
(It removes the control the core stylesheets are loaded in, removing individual stylesheets is not possible)
This means you have to add the style sheet(s) you do want to load using AddCssFile.
It's a bit of work on the skin, but I guess most people are using the Stylehelper skin object to load only skin.css and unload the rest.