Sitecore – IMS (If-Modified-Since) request header for Media Items

We recently had an issue related to media item response status. While a CDN service was making a request to access Sitecore Media item and current date is passed in if-modified-since request header, response status code was always 200. However requested media items were not modified since a long time and response status code should be 304. To troubleshoot this issue when I explore the Sitecore code (MediaRequestHeader) , found that Sitecore has exact match logic to compare the “If-Modified-Since” with media item modified date. It means if a media item is modified lets say on “01/01/2018 01:00:00 PM” and request header has value “If-Modified-Since:Mon, 01 Jan 2018 01:00:00” it will give 304 status code. Any request which has any other date or time will always respond with 200 status code.

To fix this issue there are multiple approaches and choice can be based on your project condition.

  1. While CDN is making a call to Sitecore server for media item , it should pass the last modified date of file which CDN received as response on first request. .
  2. Override the Sitecore implementation to compare the dates in MediaRequestHeader
  3. Open a ticket with Sitecore to check if they have any patch for it

Sitecore Customize Media Provider

There are scenarios when you have to customize/override Sitecore default media provider. Like in my case we enabled Akamai (CDN) for media items and  requirement was to generate the media items url using Akamai domain rather than site domain.  There are other scenarios also where you may have to customize media provider.

So to customize media provider

  • Create a new public class and inherit it from resource.Media.MediaProvider class and Sitecore.Events.Hooks.IHook Interface, like
public class CustomMediaProvider : MediaProvider, Sitecore.Events.Hooks.IHook
  • Create initialize method
public void Initialize()
        {
            MediaManager.Provider = this;
        }

  • Create constructor of class and create mediacreator object
public CustomMediaProvider ()
        {
            OverrideMediaCreator();
        }

        protected void OverrideMediaCreator()
        {
            Sitecore.Resources.Media.MediaCreator mediaCreator = GetMediaCreator();
            if (mediaCreator == null)
            {
                return;
            }

            Creator = mediaCreator;
        }

        protected virtual Sitecore.Resources.Media.MediaCreator GetMediaCreator()
        {
            return Factory.CreateObject("mediaLibrary/mediaCreator", false) as MediaCreator;
}
  • Override the GetMediaUrl and customize the code as per your need
public override string GetMediaUrl(MediaItem item)
        {
            return GetCDNURL(base.GetMediaUrl(item));
        }

        public override string GetMediaUrl(MediaItem item, MediaUrlOptions options)
        {
            return GetCDNUrl(base.GetMediaUrl(item, options));
        }

  • Do a entry in custom patch file
<sitecore>
<hooks>
      <hook  type="Assembly.Namespace.CustomMediaProvider, Assembly Details">
      </hook>
    </hooks>
</sitecore>
  •  Complete code is as follows
public class CustomMediaProvider : MediaProvider,IHook
    {
        public void Initialize()
        {
            MediaManager.Provider = this;
        }

        public override string GetMediaUrl(MediaItem item)
        {
            return GetCDNUrl(base.GetMediaUrl(item));
        }

        public override string GetMediaUrl(MediaItem item, MediaUrlOptions options)
        {
            return GetCDNUrl(base.GetMediaUrl(item, options));
        }

        string GetCDNUrl (string url)
        {
            ….
        }

        public CustomMediaProvider ()
        {
            OverrideMediaCreator();
        }

        protected void OverrideMediaCreator()
        {
            Sitecore.Resources.Media.MediaCreator mediaCreator = GetMediaCreator();
            if (mediaCreator == null)
            {
                return;
            }

            Creator = mediaCreator;
        }

        protected virtual Sitecore.Resources.Media.MediaCreator GetMediaCreator()
        {
            return Factory.CreateObject("mediaLibrary/mediaCreator", false) as MediaCreator;
        }
    }