Advanced Base64 image extension in ASP.NET MVC

Advanced base64 image rendering in a Razor in ASP.NET MVC

Serializing images to base64 string is well known technique to reduce requests per page. Each image on the page produces a separate request while page is loading. In case you have a lot of images on your page, this may cause slow lading.

Good practice is also to reference all images in your CSS file, but for now we are going to focus on loading serialized base64 image in the document directly.

Since loading image is an IO operation and it will affect performances we will also cache the serialized result and create dependency on the file.

This is basically a helper, so we can keep all static s we can call it from any place in our Razor.

namespace Mvc.Razor.Helpers
{
public static class Extensions
{
public static MvcHtmlString Base64Image(this HtmlHelper htmlHelper, String path, IDictionary<String, String> attributes = null)
{
var context = HttpContext.Current;
var builder = new TagBuilder("img");
var physicalPath = htmlHelper.ViewContext.RequestContext.HttpContext.Server.MapPath(path);
String cacheKey = path;
String cachedContent = context.Cache.Get(cacheKey) as String;
if (attributes != null && attributes.Any())
{
foreach (var attribute in attributes)
{
builder.Attributes.Add(attribute.Key, attribute.Value);
}
}
if (cachedContent == null)
{
if (File.Exists(physicalPath))
{
using (var fileStream = new FileStream(physicalPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))//No lock on a file
{
String srcTemplate = "data:image/{0};base64,{1}";
String fileExtension = Path.GetExtension(physicalPath);
byte[] buffer = new byte[fileStream.Length];
fileStream.Read(buffer, 0, (int)fileStream.Length);
if (fileExtension.StartsWith("."))
{
fileExtension = fileExtension.Substring(1).ToLower();
}
cachedContent = string.Format(srcTemplate,fileExtension, Convert.ToBase64String(buffer));
                            context.Cache.Insert(cacheKey, cachedContent, new System.Web.Caching.CacheDependency(physicalPath), DateTime.MaxValue, TimeSpan.FromHours(1));
                        }
                    }
                }
            
            builder.Attributes["src"] = cachedContent;

            return MvcHtmlString.Create(builder.ToString());
        }
}
}
    

To use this helper you will have to reference it in your Web.Config which is in your Views folder as following:

  <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization"/>
        <add namespace="System.Web.Routing" />
        <add namespace="Mvc.Razor.Helpers" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>
    

After altering Views web.config, we are ready to use the extension in our Razor views:

@Html.Base64Image("~/Content/logo_aspmvc.png")
    

I also added an optional dictionary parameter, so that you can add any attribute to the output tag.

@Html.Base64Image("~/Content/logo_aspmvc.png", new Dictionary<String, String>() { { "Title","ASP.NET MVC Logo" } })
    

Disclaimer

Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.


About the author

DEJAN STOJANOVIC

Dejan is a passionate Software Architect/Developer. He is highly experienced in .NET programming platform including ASP.NET MVC and WebApi. He likes working on new technologies and exciting challenging projects

CONNECT WITH DEJAN  Loginlinkedin Logintwitter Logingoogleplus Logingoogleplus

JavaScript

read more

SQL/T-SQL

read more

Umbraco CMS

read more

PowerShell

read more

Comments for this article