Caching is Key
As the others have said, you've got to use caching since you are performing repetitive disk I/O on data that doesn't change often.
My example creates and caches a List<T>
of the image file paths you will need for each subsequent request. System.Web.Caching
is perfect for this because you can create a CacheDependency
object directly on your image directory -- if a file gets changed or added, your cache is automatically invalidated. It is then recreated the next time it is requested.
Avoiding Duplicates with the HashSet<T>
I bet you don't want two of the same pictures ever showing up in your header!
Randomizing using Random.Next
does not exclude previously generated duplicates. I used a HashSet<T>
as a poor man's unique randomizer since the HashSet<T>
will only allow you to add unique values.
The Model
This operation should be part of your model in MVC. You change it to go along with your other data fetching classes as you see fit.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Caching;
public class RandomImage
{
public static string[] GetImages(string folder, int count)
{
HttpContext context = HttpContext.Current;
string virtualFolderPath = string.Format("/content/{0}/", folder);
string absoluteFolderPath = context.Server.MapPath(virtualFolderPath);
Cache cache = context.Cache;
var images = cache[folder + "_images"] as List<string>;
// cache string array if it does not exist
if (images == null)
{
var di = new DirectoryInfo(absoluteFolderPath);
images = (from fi in di.GetFiles()
where fi.Extension.ToLower() == ".jpg" || fi.Extension.ToLower() == ".gif"
select string.Format("{0}{1}", virtualFolderPath, fi.Name))
.ToList();
// create cach dependency on image randomFolderName
cache.Insert(folder + "_images", images, new CacheDependency(absoluteFolderPath));
}
Random random = new Random();
var imageSet = new HashSet<string>();
if (count > images.Count())
{
throw new ArgumentOutOfRangeException("count");
}
while (imageSet.Count() < count)
{
//using an hashset will ensure a random set with unique values.
imageSet.Add(images[random.Next(count)]);
}
return imageSet.ToArray();
}
}
The Controller
Access the method in your controller something like....
string[] images = Models.RandomImage.GetImages("myPictures", 4);