Notice: Due to size constraints and loading performance considerations, scripts referenced in blog posts are not attached directly. To request access, please complete the following form: Script Request Form Note: A Google account is required to access the form.
Disclaimer: I do not accept responsibility for any issues arising from scripts being run without adequate understanding. It is the user's responsibility to review and assess any code before execution. More information

Building a Dynamic Full-Screen Image Slideshow with ASP.NET


I recently needed to modernise a slideshow created by different tabs hosting images that then used a tab revolver by creating a dynamic slideshow that would automatically display all images from the same folder as my ASP.NET page. The requirements were quite specific: full-screen display, automatic detection of new images without page refresh, configurable timing between slides, and smooth professional transitions.

Requirements

The slideshow needed to:

  • Display all images from the current folder in full-screen mode
  • Automatically scan for newly added or removed images without requiring a page refresh
  • Use a configurable variable to control the timeout between slides
  • Provide smooth, professional transitions between images
  • Work on an IIS server with ASP.NET support

Simple Solution

I developed a single-file solution using ASP.NET that combines both the slideshow display and the server-side image scanning in one index-autorefresh.aspx file. This approach keeps everything simple while providing all the required functionality.

Key Features Implemented

1. Configurable Timing Variables

I made the slideshow timing easily adjustable with clear configuration variables:

// Configuration
const SLIDE_DURATION = 15000; // 15 seconds between slides
const FADE_DURATION = 1500;   // 1.5 seconds fade transition
const CHECK_INTERVAL = 5000;  // Check for new images every 5 seconds

This approach allows me to quickly modify timing without hunting through the code.

2. Professional Fade Transitions

Instead of abrupt show/hide transitions, I implemented smooth CSS-based fade effects:

.slide {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 1.5s ease-in-out;
}
.slide.active {
  opacity: 1;
}

The slides are positioned absolutely and overlay each other, with opacity transitions creating a cinematic fade effect.

3. Full-Screen Display

I achieved true full-screen presentation by making the container cover the full avaliable window, with the browser in F11 mode:

.slideshow-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}

Images use object-fit: to fill the screen completely while maintaining aspect ratio.

5. Smart Update Logic

When changes are detected, the slideshow updates seamlessly without interrupting the current flow:

if (JSON.stringify(newImages.sort()) !== JSON.stringify(currentImages.sort())) {
  console.log('Images updated - refreshing slideshow');
  updateSlideshow(newImages);
  
  if (newImages.length > 1) {
    clearTimeout(slideTimer);
    slideTimer = setTimeout(showSlidesAuto, SLIDE_DURATION);
  }
}

I use JSON string comparison to detect changes and sort the arrays to handle reordering gracefully.

Server-Side Image Scanning

The ASP.NET page dynamically scans for image files using the following logic:

<%
string[] allowedExtensions = {".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp"};
string currentPath = Server.MapPath(".");
string[] files = Directory.GetFiles(currentPath);

for (int i = 0; i < files.Length; i++)
{
    string fileName = Path.GetFileName(files[i]);
    string extension = Path.GetExtension(fileName).ToLower();
    
    if (Array.IndexOf(allowedExtensions, extension) >= 0)
    {
        Response.Write("\"" + fileName + "\"");
        // Add comma if more images follow
    }
}
%>

This scans the current directory and filters for common image formats, if you have other you may need to add them to that code!

Smooth Transition Logic

The transition logic maintains timing consistency while providing smooth visual flow:

function showSlidesAuto() {
  if (slides.length <= 1) {
    slideTimer = setTimeout(showSlidesAuto, SLIDE_DURATION);
    return;
  }
  
  slides[slideIndex].classList.remove("active");
  slideIndex = (slideIndex + 1) % slides.length;
  slides[slideIndex].classList.add("active");
  
  slideTimer = setTimeout(showSlidesAuto, SLIDE_DURATION);
}

Script : index-autorefresh.aspx

<%@ Page Language="C#" %>
<%@ Import Namespace="System.IO" %>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Auto Slideshow</title>
  <style>
    body {
      margin: 0;
      background: #111;
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
    }
    .slideshow-container {
      position: fixed;
      top: 0;
      left: 0;
      width: 100vw;
      height: 100vh;
      overflow: hidden;
    }
    .slide {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      opacity: 0;
      transition: opacity 1.5s ease-in-out;
    }
    .slide.active {
      opacity: 1;
    }
    .slide img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      background: #000;
    }
  </style>
</head>
<body>
<div class="slideshow-container" id="slideshow"></div>
<script>
  // Images dynamically generated from server
  const images = [
    <%
    string[] allowedExtensions = {".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp"};
    string currentPath = Server.MapPath(".");
    string[] files = Directory.GetFiles(currentPath);
    
    for (int i = 0; i < files.Length; i++)
    {
        string fileName = Path.GetFileName(files[i]);
        string extension = Path.GetExtension(fileName).ToLower();
        
        if (Array.IndexOf(allowedExtensions, extension) >= 0)
        {
            Response.Write("\"" + fileName + "\"");
            if (i < files.Length - 1)
            {
                // Check if there are more image files coming
                bool hasMoreImages = false;
                for (int j = i + 1; j < files.Length; j++)
                {
                    string nextExt = Path.GetExtension(Path.GetFileName(files[j])).ToLower();
                    if (Array.IndexOf(allowedExtensions, nextExt) >= 0)
                    {
                        hasMoreImages = true;
                        break;
                    }
                }
                if (hasMoreImages) Response.Write(",\n    ");
            }
        }
    }
    %>
  ];

  // Configuration
  const SLIDE_DURATION = 15000; // 15 seconds between slides
  const FADE_DURATION = 1500;   // 1.5 seconds fade transition
  const CHECK_INTERVAL = 5000;  // Check for new images every 5 seconds

  let slideIndex = 0;
  let currentImages = [];
  let slides = [];
  let slideTimer = null;
  const container = document.getElementById("slideshow");

  // Get current images from server (reloads the same page)
  async function getCurrentImages() {
    try {
      const response = await fetch(window.location.href + '?t=' + Date.now());
      const text = await response.text();
      
      // Extract image array from the server response
      const match = text.match(/const images = \[([\s\S]*?)\];/);
      if (match) {
        const imageStr = match[1];
        const imageArray = imageStr.split(',').map(s => s.trim().replace(/['"]/g, ''));
        return imageArray.filter(img => img.length > 0);
      }
      return [];
    } catch (error) {
      console.error('Error checking for images:', error);
      return currentImages;
    }
  }

  // Update slideshow with new images
  function updateSlideshow(newImages) {
    // Clear existing slides
    container.innerHTML = '';
    
    if (newImages.length === 0) {
      container.innerHTML = '<div style="color: white; text-align: center; line-height: 100vh;">No images found</div>';
      return;
    }
    
    // Create new slide elements
    newImages.forEach((src, index) => {
      let div = document.createElement("div");
      div.classList.add("slide");
      if (index === slideIndex % newImages.length) div.classList.add("active");
      let img = document.createElement("img");
      img.src = src + '?t=' + Date.now(); // Cache busting for updated images
      div.appendChild(img);
      container.appendChild(div);
    });
    
    slides = document.querySelectorAll(".slide");
    
    // Adjust slideIndex if it's beyond the new array length
    if (slideIndex >= newImages.length && newImages.length > 0) {
      slideIndex = 0;
      slides[0].classList.add("active");
    }
    
    currentImages = newImages;
  }

  // Check for image changes
  async function checkForChanges() {
    const newImages = await getCurrentImages();
    
    // Compare arrays to see if they've changed
    if (JSON.stringify(newImages.sort()) !== JSON.stringify(currentImages.sort())) {
      console.log('Images updated - refreshing slideshow');
      updateSlideshow(newImages);
      
      // Restart slideshow if we have images
      if (newImages.length > 1) {
        clearTimeout(slideTimer);
        slideTimer = setTimeout(showSlidesAuto, SLIDE_DURATION);
      }
    }
    
    // Schedule next check
    setTimeout(checkForChanges, CHECK_INTERVAL);
  }
  
  function showSlidesAuto() {
    if (slides.length <= 1) {
      slideTimer = setTimeout(showSlidesAuto, SLIDE_DURATION);
      return;
    }
    
    // Remove active class from current slide
    slides[slideIndex].classList.remove("active");
    
    // Move to next slide
    slideIndex = (slideIndex + 1) % slides.length;
    
    // Add active class to new slide
    slides[slideIndex].classList.add("active");
    
    // Schedule next transition
    slideTimer = setTimeout(showSlidesAuto, SLIDE_DURATION);
  }

  // Initialize slideshow with server-generated list first
  updateSlideshow(images);
  
  if (images.length > 1) {
    slideTimer = setTimeout(showSlidesAuto, SLIDE_DURATION);
  }
  
  // Start checking for changes after initial load
  setTimeout(checkForChanges, CHECK_INTERVAL);
</script>
</body>
</html>

Usage

  1. Place the code above in a file in the same directory as your images (using UTF-8 encoding)
  2. Ensure your IIS server has ASP.NET enabled
  3. Add or remove images from the folder - they'll appear/disappear automatically within 5 seconds

The solution provides a professional, maintenance-free slideshow that adapts to content changes in real-time, perfect for digital signage or presentation scenarios where content updates frequently.

Previous Post Next Post

نموذج الاتصال