Learn More





DNN Community Blog

The Community Blog is a personal opinion of community members and by no means the official standpoint of DNN Corp or DNN Platform. This is a place to express personal thoughts about DNNPlatform, the community and its ecosystem. Do you have useful information that you would like to share with the DNN Community in a featured article or blog? If so, please contact .

The use of the Community Blog is covered by our Community Blog Guidelines - please read before commenting or posting.

DnnImageHandler - hot or not ?

All started with a facebook conversation about a little tweak I found to help me massively with a problem I had in a website that I built for my wife.

I had to explain her the structure of her cattery website ( full of custom built modules mixed with Html-module parts.

I had the idea to hack dnn a little bit and with some research I found a possibility to blend in the module title in the drag bar. Only two additional lines of code in a dnn javascript file and three additional properties in a css class were enough too see a perfect structure in design mode and perfect kitten baby presentations in view mode - Yeah, mission completed!


Those are the tweaks:

in \Resources\Shared\scripts\dnn.dragDrop.js: (ca Zeile 104)

        for (var moduleNo = 0; moduleNo < $modules.length; moduleNo++) {
            $module = $($modules[moduleNo]);
            mid = getModuleId($module);
            moduleName = $module.attr("class").split(' ')[1].replace("DnnModule-", "");

            //Add a drag handle
            if ($module.find(".dnnDragHint").length === 0) {
                $module.prepend("<div class=\"dnnDragHint\">&amp;nbsp;" + moduleName + " (ID:" + mid + ")</div>");

            //Add a drag hint
                helpContent: settings.dragHintText,
                holderId: "ModuleDragToolTip-" + mid

in \Resources\Shared\stylesheet\dnn.dragDrop.css:

.dnnDragHint {
    background-color: black;
    color: white;
    cursor: move;
    font-family: Arial;
    font-size: 12px;
    height: 22px !important;
    outline: 1px dashed #ccc;

I loved this nice tweak, so I started a facebook post :


A lot of people commented on this thread and came up with many ideas what should also be shown....  but not in the dragbar (very small modules etc. ...).

So this came in my mind:


Yep, nice design. Must be a popup when hovering over the i-Button.

My first idea was to write a web service method which is called by client site code. This should sample the infos from dnn and create some html, styles etc. and show this html in the popup. But from the design-point  this is a nightmare. Different styles have to be considered and in every theme it looks different - a bad choice for people who use dnn as admins and have to work with modules on a daily base.

This rotated a few days in my mind and one morning I had the idea! Showing this as an image when hovering over "info" is really easy to do. All we need is an imagehandler like the "profilepic" from dotnetnuke (creates the user profile photos ). Adding  the moduleid and the tabid to the image url should be enough to retrieve all the needed information.

My bbimagehandler on codeplex is working much in the same technology. It bases on an 7 years old codeplex project from Microsoft. It was more a good architectural shell for an image handler than a final product:


see here: in detail.


Over the years (I started my project in June 2011) ,I restructured the project and added a lot of gimmics here and there. The original code generates bad rendering results and I added another, a better Quantizer (OctreeQuantizer) to the ImageQuantization. Thanks to the guy who posted this class somewhere in the internet ! (This is not my specialization ;-) )

Inside the imagehandler we have three main parts:

  • StartTransform: Is generating the main image (profile pic, image from disk, ...)
  • Filtertransform: These transforms change the main image (greyscale, resize etc.) 
    • ImageQuantization: Mathematical operations for filters
  • And the "engine" : ImageHandler main and base classes: 
    • Reading the parameters, 
    • Initiating the pipeline
    • Adding dependend on "mode" parameter the selected start transformation to the pipeline
    • Adding dependend on other parameters the additional filters with their corresponding parameter values to the pipeline
  • Running the pipeline and return the resulting image


The project is well structured in the same manner so you can see easy whats going on:


Recently I made a short introduction in the last MVP online meeting and the first questions that came up were:

What about caching ? 

As said above,the imagehandler is based on an old but robust framework for image generation in by the Microsoft guys himself.  I think they wrote it an the beginning days of ASP.NET to demonstrate the power of the product. It have had also full Visual Studio Designer mode support by a ton of additional [attributes] in the source code. (I threw them out here because we don't need this in our image enigine room).

The imagehandler has full support for server site AND client site caching. Server site caching is done by building a unique hash key over the parameters and save this generated image to a subdirectory in App_Data. Client site caching is done by sending the appropiate 304 Headers - this works all well out of the box.

Did you implement security ?

What about DDOS scenarios generating tons of images with different sizes that let the cache explode (Shaun himself asked this question, remembering some issues they had with the original profile pic handler in DNN) ? Thats a point I had not thought about, but finally I found a solution; its all in the IPCount.cs class. On every hit to the imagehandler IPCount retrieves the IP address of the requester and looks for a file in App_data/_IPCount folder with the same name as this IP address. If found, it opens the file and reads the number in it and compares it to the maxAllowed value. If this border is hit, the imagehandler returns a 403 http status code (IP address rejected), if not the number is incremented by 1 and saved back to the file. If no writing appears into the file for a specified time (LastWriteTime) the file is automatically deleted.

What about other websites that "steale" my images ?

I created a config option to allow or disallow invoking the imagehandler as a "standalone" image (as typing the image url directly into the browser) and additionally to define which domains are allowed to incude images into their website. 

What is implemented "Out of the box" ?

Enabling the image handler functionality is done by an additional statement in the system.webServer/handlers section of web.config:

<add name="DnnImageHandler" path="DnnImageHandler.ashx" verb="*" type="DotNetNuke.Services.GeneratedImage.DnnImageHandler, DotNetNuke" preCondition="integratedMode" />

The image handler could be used if you enter the following image url:;param1=value1&amp;param2=value2...

There are a few modes (StartTransform) defined:

  • profilepic – shows the profile picture to a given userid (if allowed) or a generic “no avatar” image
  • file – shows an image by given filename with path or an url or filepath and index (alphabetical order)
  • securefile – shows the image by a given fileid (if allowed). If no image format shows filetype icon instead
  • placeholder – shows a rectangle with image dimensions or text on it
  • modinfo – shows some information about a specific module on a page like title, skin etc.

These “modes” are generating an image. The generated image could be modified by additional parameters. Available modifications (FilterTransform) are:

  • Resize – defining the dimension of the resulting image with different resize modes, Adding borders and colored background
  • Format – define the resulting format of the generated image (jpg, png…)
  • Gamma – adjust the gamma value
  • Brightness – adjust the brightness value
  • Contrast – adjust the contrast value
  • Greyscale – convert to greyscale image
  • Invert – convert to negative image
  • Rotate + Flip – rotate and / or flip the image

Mode: Profilepic

The profilepic mode shows the profile picture to a given userid (if allowed) or a generic “no avatar” image. The functionality is the same as the old profilepic.ashx handler.





ID of user whose profile image should be shown. If omitted, the profile pic of the current user is generated. If no user is logged in or the profile pic is not allowed to show, a generic avatar image is generated

<img src="/dnnimagehandler.ashx?mode=profilepic&w=120" />
<img src="/dnnimagehandler.ashx?mode=profilepic&userid=2&w=120" />


Mode: File

The file mode shows an image by given filename with path or url or filepath and index (alphabetical order)





Relative path to the file incl. filename, eg: /Portals/0/images/myimage.gif





Url to image (url-encoded), eg:





Relative path to a folder containing images


Index of the file in the folder (starting with 1, alphabetical order)

<img src="/dnnimagehandler.ashx?mode=file&file=Portals/0/Images/icon-qa.png&size=xs" />

<img src="/dnnimagehandler.ashx?mode=file&" />

<img src="/dnnimagehandler.ashx?mode=file&path=Portals/0/Images&index=5" />


Mode: Securefile

The securefile mode shows the image by a given fileid (if allowed). If no image format shows filetype icon instead





Shows the image with the given fileid if the logged user has the view permission for this file. If the file is no image file, an icon is generated instead (from file icons/Sigma/ext%EXTENSION%_32x32_standard.png)

<img src="/dnnimagehandler.ashx?mode=securefile&fileid=100" /> (skin.css)

<img src="/dnnimagehandler.ashx?mode=securefile&fileid=101" /> (1-icn.png)


Mode: Placeholder

The placeholder mode shows a rectangle with image dimensions or text on it





Width in pixel


Height in pixel


Foreground color


Background color


Text to display on image. If omitted, dimensions are shown

<img src="/dnnimagehandler.ashx?mode=placeholder&w=150&h=100&text=plugin-modul" />

<img src="/dnnimagehandler.ashx?mode=placeholder&w=150&h=100&color=yellow&backcolor=green" />


Mode: Modinfo

The modinfo mode shows some information about a specific module on a page like title, skin etc.





Module id of the module


Tab Id of the page where the module is located

<img alt="" src="/dnnimagehandler.ashx?mode=modinfo&moduleid=415&tabid=55" />



Defining the dimension of the resulting image with different resize modes, Adding borders and colored background.





Width of Image


Height of Image


Predefined size of image: xxs: 16x16, xs:32x32, s:50x50, l:64x64, xl:128x128, xxl:256x256


Instead of Width this can be used to leave the picture as it is until the width reaches the max value.


Instead of Height this can be used to leave the picture as it is until the height reaches the max value.


· fit mode maintains the aspect ratio of the original image while ensuring that the dimensions of the result do not exceed the maximum values for the resize transformation. (Needs width or height parameter)

· fitsquare resizes the image with the given width as its longest side (depending on image direction) and maintains the aspect ratio. The image will be centered in a square area of the chosen background color (Needs width parameter, backcolor optional)

· crop resizes the image and removes parts of it to ensure that the dimensions of the result are exactly as specified by the transformation.(Needs width and height parameter)

· fill resizes the image with the given width or height without maintaing the aspect ratio.


color of background or/and border when resizemode is fitsquare or fit


border width in pixels around the image (added to width / height) when resizemode is fitsquare or fit.

<img src="/dnnimagehandler.ashx?mode=profilepic&userid=2&size=xl&backcolor=%23F58719&border=10" />

<img src="/dnnimagehandler.ashx?mode=file&file=Portals/0/Images/icon-qa.png&h=128&w=40&resizemode=fill" />



Adjusting the gamma value





Value for gamma adjustment between 0.2 and 5

<img src="/dnnimagehandler.ashx?mode=profilepic&userid=2&size=xl&gamma=4"/>



Adjusting the brightness value





Value for brightness adjustment between -255 and +255

<img src="/dnnimagehandler.ashx?mode=profilepic&userid=2&size=xl&brightness=128" />


Filter: Contrast

Adjusting the contrast value





Value for contrast adjustment between -100 and +100

<img src="/dnnimagehandler.ashx?mode=profilepic&userid=2&size=xl&contrast=75" />


Filter: Greyscale

Convert image to greyscale





If present, image is converted to greyscale (needs dummy value, e.g “1”)

<img src="/dnnimagehandler.ashx?mode=profilepic&userid=2&size=xl&greyscale=1" />



Converts an image to its negative representation





If present, image is inverted (needs dummy value, e.g “1”)

<img src="/dnnimagehandler.ashx?mode=profilepic&userid=2&size=xl&invert=1" />


Filter: Rotateflip

Rotates and / or flips the image





RotateNoneFlipNone: Specifies no clockwise rotation and no flipping.

Rotate90FlipNone: Specifies a 90-degree clockwise rotation without flipping.

Rotate180FlipNone: Specifies a 180-degree clockwise rotation without flipping.

Rotate270FlipNone: Specifies a 270-degree clockwise rotation without flipping.

RotateNoneFlipX: Specifies no clockwise rotation followed by a horizontal flip.

Rotate90FlipX: Specifies a 90-degree clockwise rotation followed by a horizontal flip.

Rotate180FlipX: Specifies a 180-degree clockwise rotation followed by a horizontal flip.

Rotate270FlipX: Specifies a 270-degree clockwise rotation followed by a horizontal flip.

RotateNoneFlipY: Specifies no clockwise rotation followed by a vertical flip.

Rotate90FlipY: Specifies a 90-degree clockwise rotation followed by a vertical flip.

Rotate180FlipY: Specifies a 180-degree clockwise rotation followed by a vertical flip.

Rotate270FlipY: Specifies a 270-degree clockwise rotation followed by a vertical flip.

RotateNoneFlipXY: Specifies no clockwise rotation followed by a horizontal and vertical flip.

Rotate90FlipXY: Specifies a 90-degree clockwise rotation followed by a horizontal and vertical flip.

Rotate180FlipXY: Specifies a 180-degree clockwise rotation followed by a horizontal and vertical flip.

Rotate270FlipXY: Specifies a 270-degree clockwise rotation followed by a horizontal and vertical flip.

<img src="/dnnimagehandler.ashx?mode=profilepic&userid=2&size=xl&rotateflip=Rotate90FlipY" />

<img src="/dnnimagehandler.ashx?mode=profilepic&userid=2&size=xl&rotateflip=RotateNoneFlipY" />

<img src="/dnnimagehandler.ashx?mode=profilepic&userid=2&size=xl&rotateflip=RotateNoneFlipX" />



There are a few options for the imagehandler that could be set up via configuration in web.config. You could set your options in appSettings-section:

<add key="DnnImageHandler" value="EnableIpCount=false;AllowStandalone=false;LogSecurity=true;,;EnableServerCache=true;EnableClientCache=true;" />

The following options are available :




Default: true. If true, every generation of an image will be counted. If IPCountMax is hit no more images are generated until IPCountPurgeInterval is up. Physically there is a file in App_Data/_ipcount for every IP containing the number of hits. When IPCountPurgeInterval is over, this file is deleted.


Default: 200. Max number of hits from an IP allowed in defined time span IPCountPurgeInterval


Default: 300. Seconds for measuring the hits from one IP.


Default: true. Enables the server side caching of images in folder App_Data/_images


Default: 180. Seconds until the image is deleted from image cache folder and generated again.


Default: true. Enables the client side caching of images (answering with 304 http response until ClientCacheExpiration is reached)


Default: 60. Seconds caching the image on client site.


Default: false. If true, Images could be shown standalone via image url. If false, only images integrated in a web page (referrer is not null) are shown, others return 403 (forbidden) http status code.


Default: false. If true, hitting IPCountMax or AllowStandalone bounderies produce a eventlog entry


Default: empty string. By default, all websites are allowed as referrer. Include here a comma-separated list of domains to restrict the embedding of your images to pages from these domains (e.g., )


Default: 95. Set the image generation quality. Range is from 0 to 100.

But: Thats not all! The DnnImageHandler is extensible by third party developers!

Additional Mode Extensions

If a developer creates a dll containing a class (for example: PercentTransform) based on ImageTransform class with two public property named “percentage” and "color":

using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;

namespace Dotnetnuke.Web.GeneratedImage.Transform
        public class ImagePercentTransform : ImageTransform
               /// <summary>
               /// Sets the percentage value for the radial indicator
               /// </summary>
               public int Percentage { get; set; }

               /// <summary>
               /// Sets the Color of the indicator element
               /// </summary>
               public Color Color { get; set; }

               public override string UniqueString
                      get { return base.UniqueString + this.Percentage.ToString() + "-" + this .Color.ToString(); }

               public ImagePercentageTransform()
                     InterpolationMode = InterpolationMode.HighQualityBicubic;
                     SmoothingMode = SmoothingMode.HighQuality;
                     PixelOffsetMode = PixelOffsetMode.Default;
                     CompositingQuality = CompositingQuality.HighSpeed;

               public override Image ProcessImage(Image image)
                     Bitmap bitmap = new Bitmap( 100, 100);
                      using (Graphics objGraphics = Graphics.FromImage(bitmap))
                            // Initialize graphics
                           objGraphics.SmoothingMode = SmoothingMode.AntiAlias;
                           objGraphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;

                            // Fill pie
                            // Degrees are taken clockwise, 0 is parallel with x
                            // For sweep angle we must convert percent to degrees (90/25 = 18/5)
                            float startAngle = - 90.0F;
                            float sweepAngle = ( 18.0F/ 5)*Percentage;

                           Rectangle rectangle = new Rectangle( 5, 5, 90, 90);
                           Brush colorBrush = new SolidBrush(Color);
                           objGraphics.FillPie(colorBrush, rectangle, startAngle, sweepAngle);

                            // Fill inner circle with white
                           rectangle = new Rectangle( 20, 20, 60, 60);
                           objGraphics.FillEllipse(Brushes.White, rectangle);

                            // Draw circles
                           rectangle = new Rectangle( 5, 5, 90, 90);
                           objGraphics.DrawEllipse(Pens.LightGray, rectangle);
                           rectangle = new Rectangle( 20, 20, 60, 60);
                           objGraphics.DrawEllipse(Pens.LightGray, rectangle);

                            // Draw text on image
                            // Use rectangle for text and align text to center of rectangle
                            var font = new Font( "Arial" , 13 , FontStyle.Bold);
                           StringFormat stringFormat = new StringFormat();
                           stringFormat.Alignment = StringAlignment.Center;
                           stringFormat.LineAlignment = StringAlignment.Center;

                           rectangle = new Rectangle( 20, 40, 62, 20);
                           objGraphics.DrawString(Percentage + "%" , font, Brushes.DarkGray, rectangle, stringFormat);

                            // Save indicator to file
                      return (Image) bitmap;

and copy this dll to the DNN bin folder and also adds an entry to the AppSettings section of web.config like this:

<add key="DnnImageHandler.Percent" value="MyNamespace.PercentTransform, NameOfMyDll" />

he is able to invoke the imagehandler with an URL syntax like this:;percentage=30&amp;color=green


So this is a really cool extension point where developers can gain leverage from the imagehandler foundation. This is for example one extension I built for a renting module


The possibilities are endless ! Think of watermarking images in an ecommerce application or adding fancy borders to images.

So, what do you think ? Should this go into the core ? Pull request is pending! And regarding the initial idea: I promise to work on it later, even if the imagehandler will be denied. But I really believe that this one could be a really powerfull image engine for DNN and a unique feature point in competition with other CMS Systems.


Jay Mathis
Awesome work Torsten! I've used your BBImageHandler for a long time in some custom projects and I've always thought it should have been in core a long time ago.

One small suggestion about the resize filter. You may consider adopting the same functionality and names as the CSS background-size property. I think that probably handles just about everything people need to do and using the same naming convention would help with adoption and usage.
Jay Mathis Monday, February 23, 2015 8:33 PM (link)
Sebastian Leupold
sounds great, I look forward getting it included into the DNN platform.
Sebastian Leupold Wednesday, February 25, 2015 4:55 PM (link)
Phil Speth
Just a quick question.
Would this be compatible with DNN Storage providers.
Cloud storage for media is an important factor moving forward.
Phil Speth Friday, February 27, 2015 11:01 AM (link)
Torsten Weggen
Hi Phil. I'm not sure because I have no other folder provider then the standard one to test against. But I used the standard mechanism to retrieve the original image so I think it should work - and if not it should be easy to fix.
Torsten Weggen Monday, March 02, 2015 1:28 PM (link)
David O'Leary
I would love to see this added to the core.
David O'Leary Wednesday, March 11, 2015 11:00 AM (link)
Jacques Woolston
Hi Torsten,

I've just put a new DNN site live using your image handler and it's working great... a really nice module, previously I've been using my own coded resizer but switched to yours as it's got a lot more built in.

Anyway, one problem I stumbled upon using your module was that the CDN service I use (Cloudflare) would not cache the images produced by the handler, I suppose because they're not seen as static files. Obviously getting the CDN to cache the images takes a huge potential load off the server for CPU in resizing and also bandwidth. Here's what I came up with, in case it helps.

Currently for this site I always want my images in 1 of 4 sizes so I added 4 rules to DNN's friendly URL settings so I could request resized images in a format such as /ir/xxl/path-to-image.jpg which re-writes to /bbimagehandeler.ashx?width=1000&height=1000&file=path-to-image.jpg Because normally requests for images are handled by the static file provider I also created an HTTP Module to force requests to images starting with my friendly URL (/ir/) to be handled by DNN and the friendly URL provider and then the bbimagehandler.

Now CloudFlare is caching all of the images and is saving over half of the bandwidth to the site and probably saving a load of processing power too.

Perhaps some sort of implementation like this for integration to the core where custom URL's can be configured for different image requests would be a bonus. You can see it in action here:

Jacques Woolston Monday, March 30, 2015 8:50 AM (link)
Hi Torsten,

In our environment one of our website we are using BBImageHandler module. This module generates below two exception in website and causing high CPU usage and need help to configure AppSettings section for this module. Below is the Environment details.

Regarding issue 1 can you help me to setup the below suitable options..


Environment: Windows Server 2012 R2 64 bit machine
SQL Server: SQL server 2012 R2 64 bit machine
DNN Version: Evoq 8.2
Webfarm: Yes
FileSystem: Shared drive for both webserver

Current AppSettings Code in Environment:

Issue 1:
Could not find file '\\DNN\App_Data\_imagecache\C1BD0C0CAF7BEE587BE3056030C87CF7AADAC4A4.tmp'.
The process cannot access the file '\\DNN\App_Data\_imagecache\2252F4BF92F0AD0D0459050DD9CFC8E992087DD9.tmp' because it is being used by another process.
Access to the path '\\DNN\App_Data\_imagecache\40BF2670102250604F5F85374C6B3225AA8019E9.tmp' is denied.

Issue 2:
Message:Unhandled Error:
InnerMessage:BBImageHandler: Not allowed to use standalone (only localhost + localhost,)
at Bitboxx.Web.GeneratedImage.ImageHandler.ProcessRequest(HttpContext context)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Thanks in Advance!

Gopinath Tuesday, August 09, 2016 6:07 AM (link)

Comment Form

Only registered users may post comments.


2sic Daniel Mettler (125)
Aderson Oliveira (15)
Alec Whittington (11)
Alex Shirley (10)
Andrew Nurse (30)
Anthony Glenwright (5)
Antonio Chagoury (28)
Ash Prasad (22)
Ben Schmidt (1)
Benjamin Hermann (25)
Benoit Sarton (9)
Beth Firebaugh (12)
Bill Walker (36)
Bob Kruger (5)
Brian Dukes (2)
Brice Snow (1)
Bruce Chapman (20)
Bryan Andrews (1)
cathal connolly (55)
Charles Nurse (163)
Chris Hammond (203)
Chris Paterra (55)
Clinton Patterson (28)
Cuong Dang (21)
Daniel Bartholomew (2)
Dave Buckner (2)
David Poindexter (3)
David Rodriguez (2)
Doug Howell (11)
Erik van Ballegoij (30)
Ernst Peter Tamminga (74)
Geoff Barlow (6)
Gifford Watkins (3)
Gilles Le Pigocher (3)
Ian Robinson (7)
Israel Martinez (17)
Jan Blomquist (2)
Jan Jonas (3)
Jaspreet Bhatia (1)
Jenni Merrifield (6)
Joe Brinkman (270)
John Mitchell (1)
Jon Henning (14)
Jonathan Sheely (4)
Jordan Coopersmith (1)
Joseph Craig (2)
Kan Ma (1)
Keivan Beigi (3)
Ken Grierson (10)
Kevin Schreiner (6)
Leigh Pointer (31)
Lorraine Young (60)
Malik Khan (1)
Matthias Schlomann (15)
Mauricio Márquez (5)
Michael Doxsey (7)
Michael Tobisch (3)
Michael Washington (202)
Mike Horton (19)
Mitchel Sellers (28)
Nathan Rover (3)
Navin V Nagiah (14)
Néstor Sánchez (31)
Nik Kalyani (14)
Peter Donker (52)
Philip Beadle (135)
Philipp Becker (4)
Richard Dumas (22)
Robert J Collins (5)
Roger Selwyn (8)
Ruben Lopez (1)
Ryan Martinez (1)
Salar Golestanian (4)
Sanjay Mehrotra (9)
Scott McCulloch (1)
Scott S (11)
Scott Wilkinson (3)
Scott Willhite (97)
Sebastian Leupold (80)
Shaun Walker (237)
Shawn Mehaffie (17)
Stefan Cullmann (12)
Stefan Kamphuis (12)
Steve Fabian (31)
Timo Breumelhof (24)
Tony Henrich (3)
Torsten Weggen (2)
Vicenç Masanas (27)
Vincent Nguyen (3)
Vitaly Kozadayev (6)
Will Morgenweck (37)
Will Strohl (163)
William Severance (5)
Try Evoq
For Free
Start Free Trial
a Demo
See Evoq Live
Need More Information?