Displaying Random Images in an ASP.NET Web Page
By Scott Mitchell
Introduction
As web developers, we most often focus on backend web developer, buring our noses in defining and implementing the business
logic, building CRUDs, and designing reports.
Rarely are we concerned about maintaining the appearance and style of the website. For developers working in medium- to
large-sized companies, this poses no problem as there are graphic designers whose job it is to design a slick layout and
periodically update it in order to keep the site from becoming stale. In smaller companies, however, oftentimes the web
developer writing the backend code is also the one responsible for maintaining the frontend.
One easy and cost-effective way of keeping a site from becoming stale is to display different images on a page each time
it is visited. Many corporate websites use this technique on their homepages. For example, the homepage might have
a picture of a facility or employees in the upper right hand corner. Rather than showing a single, static picture,
each time the homepage is visited a randomly selected image is displayed.
There are a couple of ways to display random images, and this article will look at two different approaches. The first
technique covered in this article is to simply display a randomly selected image file from a directory of files. This
simplistic approach is easy to implement but is limited in a number of ways. We'll also look at a more professional
approach that utilizes a free, open-source ContentRotator control I created back in September 2005. With the my ContentRotator
control where you can specify what images, exactly, are candidates for being displayed as well as how likely a particular
image should be selected relative to the other images in the image set. Read on to learn more!
Randomly Displaying an Image from a Directory of Images
The easiest way to display a random image is to add an ASP.NET Image control to your page (or Master Page) and to write
a little code that gets all of the image files from a particular directory, uses the Random
class to randomly pick an image from the list, and assings the randomly selected image's path to the ASP.NET Image control's
ImageUrl property. This can all be done in under 10 lines of code.
To illustrate the techniques we will discuss in this article, I created a simple ASP.NET 2.0 demo application that you can
download from the end of this article. This demo includes a Master Page named ImagesFromDirectory.master that
defines an 800 pixel wide page layout. In the top 250 pixels of the page you'll find an ASP.NET Image control named HeaderImage
that displays a randomly selected image. The ~/Images/HeaderImages/ folder contains five images that are sized to
precisely 800x250 pixels. The PickImageFromDirectory(directoryPath) method, shown below, returns the path
to a randomly selected image. This method is called from the Master Page's Page_Load event handler, where its
return value is assigned to the Image control's ImageUrl property.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
'Programmatically pick a random image from the ~/Images directory HeaderImage.ImageUrl = PickImageFromDirectory("~/Images/HeaderImages")
End If
End Sub
'Returns the virtual path to a randomly-selected image in the specified directory Private Function PickImageFromDirectory(ByVal directoryPath As String) As String
Dim dirInfo As New DirectoryInfo(Server.MapPath(directoryPath))
Dim fileList() As FileInfo = dirInfo.GetFiles()
Dim numberOfFiles As Integer = fileList.Length
'Pick a random image from the list
Dim rnd As New Random
Dim randomFileIndex As Integer = rnd.Next(numberOfFiles)
Dim imageFileName As String = fileList(randomFileIndex).Name
Dim fullImageFileName As String = Path.Combine(directoryPath, imageFileName)
Return fullImageFileName
End Function
The code starts by using the DirectoryInfo class
to get a list of all of the files in the specified directoryPath. (In this case, ~/Images/HeaderImages).
To get all of the files from the directory, the GetFiles()
method is used. (Calling GetFiles() without any input parameters returns all of the files in the
specified directory, but you can return just a subset of the files by specifying a wildcard parameter, like
dirInfo.GetFiles("*.jpg").)
The GetFiles() method returns an array of FileInfo objects. To pick a random one, we simply need
to choose a random index into this array. This is accomplished by creating a Random class instance
and calling its Next(upperBound) method to get a random number less than upperBound. We can then
determine the name of the selected file and concatenate it to the end of the supplied directoryPath.
The following two screenshots shows this code in action. The first time I visit this page the 1,000 Island Lake picture
was randomly selected.
I then refreshed the page. This time, the Half Dome picture was the one that was randomly selected.
Displaying Random Images Using the ContentRotator Web Control
While randomly displaying an image from a directory is straightforward and easy to implement, it's simplicity limits its
overall functionality. In particular, each image in the specified directory is equally likely to be selected randomly.
Additionally, the code considers all of the images in the specified directory when choosing one. However, you may
only want a subset of the images in a directory to be considered when choosing an image to display.
Back in September 2005 I wrote an article on Microsoft's MSDN site titled
Building a ContentRotator ASP.NET Server Control, which
showcased a free, open-source content rotator control I created. Using the ContentRotator control is easy: just specify
what content items are to be considered when choosing the content item to display. The content items can be specified through
an XML file, added programmatically to the control, or hard-coded through the control's declarative syntax.
Each content item can optionally include a weighting that indicates how likely each content item is to be selected relative
to the other possible content items.
If your image information is in a database, you can programmatically add the set of images to consider for display to the
ContentRotator control's Items collection. Since there is no database in my demo application, I decided to
put the content items in an XML file:
First off, take note of the XML structure: the root element is named <contents> and each of its
children elements are named <content>. Each <content> can include an
impressions attribute, which indicates the "weight" of the content item. If no impressions value
is specified (as in the case of the second <content> element) then a value of 1 is used.
The markup that appears within the <content> tags is the actual content that will be rendered for the
selected content item. Since this is an XML file, all text within the <content>must be escaped.
That's why the < and > characters for the img element have been escaped to
< and >, respectively.
The algorithm used to determine what content item to display uses each content item's impressions attribute. The
Building a ContentRotator ASP.NET Server Control article
describes this algorithm thusly:
"The algorithm used to randomly choose a content item works by laying out each applicable content item end-to-end, forming
a line. The length of each content item is its impressions value, meaning that the total length of the line is the sum of
the applicable content items' impressions. Next, a random number less than the total length is chosen, and the content item
to display is the one that lies at the location of the random number. [The following figure] illustrates this algorithm graphically."
Since the 1,000 Island Lakes picture has an impressions value that's equal to the sum of all of the other impression values,
it will appear twice as often as any other picture.
To complete the implementation of this approach, all we need to do is add the ContentRotator control to the ASP.NET
page or Master Page where we want the random image to appear and set its ContentFile property to the path of the
XML content file. In the demo application available for download at the end
of this article I created an additional Master Page (ImagesFromContentRotator.master) that used the same
layout as ImagesFromDirectory.master. Instead of using an ASP.NET Image control, I instead added a ContentRotator
control to the header section. Using the ContentRotator control in your application involves the following steps:
Add the skmContentRotator.dll assembly to your application's /Bin directory.
At the top of the ASP.NET page or Master Page where you want to use the ContentRotator control, add the following
@Register directive: <%@ Register TagPrefix="skm" Namespace="skmContentRotator" Assembly="skmContentRotator" %>.
Add the ContentRotator control to a page by adding the following markup: <skm:ContentRotator id="ContentRotator1" runat="server" />.
Alternatively, you can bypass steps 2 and 3 above by adding the ContentRotator control to the Toolbox and then dragging
and dropping the control from the Toolbox onto your web page or Master Page.
The output of the ImagesFromContentRotator.master is identical to ImagesFromDirectory.master
except that the likelihood of the images displayed is non-uniform for the ContentRotator example.
Making the Image Path Absolute
One issue with the above content item markup is that the img elements' src attributes are
relative. That is, they do not start with a / so the path to the image is relative to the path that the
current ASP.NET page exists within. For example, in the XML content file the 1,000 Island Lakes image path is set to
"Images/HeaderImages/1000IslandLake.jpg". If the ASP.NET page that uses this Master Page is in the application's
root directory, then everything will work fine. But what if later we create a subfolder named, say, /sales,
and we add an ASP.NET page in that folder that uses the ImagesFromContentRotator.master Master Page?
If the 1,000 Island Lakes photo comes up, it will look for the file /sales/Images/HeaderImages/1000IslandLake.jpg,
which doesn't exist!
If we were using the ASP.NET Image server control we could use the ~ character in the ImageUrl
property like "~/Image/HeaderImages/1000Islandlake.jpg". At runtime, the ~ would be automatically resolved
to include the appropriate root directory. The ContentRotator control emits static output, but fires an event after it selects
the content item to display. We can create an event handler for this event and properly root the image. To accomplish this,
start by updating each image path in the src attributes to start with "~/". For example, change the
1,000 Island Lakes image path from "Images/HeaderImages/1000IslandLake.jpg" to "~/Images/HeaderImages/1000IslandLake.jpg".
The choice of ~ is so that the syntax mimics that of the ASP.NET Image control. You could use any character
here that was not already in use in the markup (such as $.)
Next, create an event handler for the ContentRotator's ContentCreated event in the Master Page's code-behind class.
In this event handler we simple replace all instances of ~ with the web application's path (available via
Request.ApplicationPath):
Protected Sub ContentRotator1_ContentCreated(ByVal sender As Object, ByVal e As skmContentRotator.ContentCreatedEventArgs) Handles ContentRotator1.ContentCreated
'Resolve image paths
e.ContentItem.Content = e.ContentItem.Content.Replace("~", Request.ApplicationPath)
End Sub
In addition to its ContentCreated event, the ContentRotator control can also display dynamic content using
User Controls. For a more thorough discussion of the ContentRotator control refer to the
Building a ContentRotator ASP.NET Server Control article.