When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article

ASP ASP.NET ASP FAQs Message Board Feedback
 
Print this Page!
Published: Wednesday, September 19, 2007

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!

- continued -

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.

A randomly selected image.

I then refreshed the page. This time, the Half Dome picture was the one that was randomly selected.

A randomly selected image.

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:

<?xml version="1.0" encoding="utf-8" ?>
<contents>
  <content impressions="16">
    &lt;img src="Images/HeaderImages/1000IslandLake.jpg" border="0" alt="1,000 Island Lake" width="100%" height="100%" /&gt;
  </content>
  <content>
    &lt;img src="Images/HeaderImages/HalfDome.jpg" border="0" alt="Half Dome" width="100%" height="100%" /&gt;
  </content>
  <content impressions="4">
    &lt;img src="Images/HeaderImages/HumphreyMountain.jpg" border="0" alt="Mt. Humphrey" width="100%" height="100%" /&gt;
  </content>
  <content impressions="2">
    &lt;img src="Images/HeaderImages/MarieLake.jpg" border="0" alt="Marie Lake" width="100%" height="100%" /&gt;
  </content>
  <content impressions="1">
    &lt;img src="Images/HeaderImages/PiuteCreek.jpg" border="0" alt="Piute Creek" width="100%" height="100%" /&gt;
  </content>
</contents>

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 &lt; and &gt;, 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:

  1. Add the skmContentRotator.dll assembly to your application's /Bin directory.
  2. 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" %>.
  3. 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.

Happy Programming!

  • By Scott Mitchell


    Further Reading


  • Building a ContentRotator ASP.NET Server Control
  • Attachments


  • Download the code used in this article
  • Download the ContentRotator control and code (from Microsoft's website)


  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article