Lazy loading of Images in ASP.Net MVC with RouteHandler and JQuery

In this short tutorial, I am going to narrate on how we can lazy load images in a ASP.Net MVC 4 page. In most of today’s social media sites, we often come across lots and lots of images which load immediately a page renders and in return kill most of the bandwidth unnecessarily. So optimizing the rendering mechanism of images with ON DEMAND feature would be a good solution in both bandwidth optimization and performance perspectives.

In the code below, I am going to demonstrate on how to create a specific Route Handler in ASP.Net MVC 4, which returns an instance of HttpHandler. HttpHandler is going to serve image to the client browser, but to make client browser not to fetch actual image URL, we have used Route Handler. Later we use JQuery LazyLoad plugin to get images only on demand i.e., only on focus. We have wide range of effects and different configuration on LazyLoad plugin, but I am settling for simple fadeIn effect for making this tutorial simple and elegant.

Lets get into some code to understand some main concepts –

First lets create a ASP.Net MVC 4 (.Net Framework 4) project in Visual studio 2010. Then add a folder – “new” in Images folder. Copy paste some images into the folder –

LazyLoading1

Then create a controller called ImagesController in Controllers folder. Place the following code in the controller –

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace ImagesLazyLoading.Controllers
{
    public class ImagesController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult LoadImages()
        {
            var list = new List<string>();

            list.Add("1.jpg");
            list.Add("2.jpg");
            list.Add("3.jpg");
            list.Add("4.jpg");
            list.Add("5.jpg");
            list.Add("6.jpg");
            list.Add("7.jpg");
            list.Add("8.jpg");
            list.Add("9.jpg");
            list.Add("10.jpg");
            
            return View(list);
        }
    }
}

Lets start creating a Route Handler to server images to the view. Place this Route Handler in Utils folder –

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;

namespace ImagesLazyLoading.Utils
{
    public class ImageRouteHandler : IRouteHandler
    {
        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            return new ImagepHandler(requestContext);
        }
    }

    public class ImagepHandler : IHttpHandler
    {
        private RequestContext _requestContext;

        public ImagepHandler(RequestContext requestContext)
        {
            _requestContext = requestContext;
        }

        public bool IsReusable
        {
            get { return false; }
        }

        public void ProcessRequest(HttpContext context)
        {
            var routeValues = _requestContext.RouteData.Values;
            if (routeValues.ContainsKey("id"))
            {
                string filename = _requestContext.HttpContext.Server.MapPath("~/Images/New/" + routeValues["id"]);
                System.IO.FileInfo fileInfo = new System.IO.FileInfo(filename);


                if (fileInfo.Exists)
                {
                    _requestContext.HttpContext.Response.Clear();
                    _requestContext.HttpContext.Response.AddHeader("Content-Disposition", "inline;attachment; filename=\"" 
                                                                    + fileInfo.Name + "\"");
                    _requestContext.HttpContext.Response.AddHeader("Content-Length", fileInfo.Length.ToString());
                    _requestContext.HttpContext.Response.ContentType = "application/octet-stream";
                    _requestContext.HttpContext.Response.TransmitFile(fileInfo.FullName);
                    _requestContext.HttpContext.Response.Flush();
                }
            }
        }
    }
}

Add the newly create Route Handler in Global.asax file –

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using ImagesLazyLoading.Utils;

namespace ImagesLazyLoading
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();

            RouteTable.Routes.Add("ImagesRoute", new Route("privateImage/{id}", new ImageRouteHandler()));
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }
    }
}

 

Now download latest JQuery LazyLoad Plugin script – http://www.intstrings.com/ramivemula/wp-content/uploads/2013/02/jquery.lazyload.js Credit to: http://www.appelsiini.net/projects/lazyload. Also please donwload JQuery 1.9.1 version latest scripts – http://www.intstrings.com/ramivemula/wp-content/uploads/2013/02/JScript_latest.js.

Place both the files in Scripts folder –

LazyLoading2

 

Finally lets create a View for our ImagesController in Views/Images folder. Include both (JQuery Latest version and Lazy Load JQuery Scripts) in the header and place the JQuery code to make image load lazily.

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>LoadImages</title>

    <script src="../../Scripts/JScript_latest.js" type="text/javascript"></script>
    <script src="../../Scripts/jquery.lazyload.js" type="text/javascript"></script>

    <script type="text/javascript">
        $(function () {
            $("img.lazy").lazyload({
                effect: "fadeIn"
            });
        });
    </script>

</head>
<body>
    <div>
    @foreach (var item in Model)
    {
      <img class="lazy" src="../../Images/new/loading.gif" data-original="/privateImage/@item" width="800" height="600" />
      <br /> 
    }
    </div>
</body>
</html>

That’s it, we are done. Now run the site using F5 and navigate to Images/LoadImages action, you will experience image lazy loading.

LazyLoading3

You may also like...

2 Pingbacks/Trackbacks