In my previous post, Pushing Images from Sitecore’s media Library to Amazon’s CDN
I set everything up to push images from Sitecore to Amazon’s CDN
The final step that needs to be performed is to update Sitecore, so that Sitecore will render the url of the image on the CDN server instead of rendering the url of the image on Sitecore.
Therefore need to create a hook for the MediaProvider
using Sitecore.Data.Items; using Sitecore.Events.Hooks; using Sitecore.Resources.Media; public class MediaProvider : Sitecore.Resources.Media.MediaProvider, IHook { public void Initialize() { MediaManager.Provider = this; } public override string GetMediaUrl(MediaItem item) { var mediaUrl = base.GetMediaUrl(item); return GetMediaUrl(mediaUrl, item); } public override string GetMediaUrl(MediaItem item, MediaUrlOptions options) { var mediaUrl = base.GetMediaUrl(item, options); return GetMediaUrl(mediaUrl, item); } /// <summary> /// Determines if we should be pulling from the CDN or not /// </summary> public string GetMediaUrl(string mediaUrl, MediaItem item) { //if the url is already expanded than ignore //(this could happen with emails) //if (mediaUrl.Contains("http")) //{ // return mediaUrl; //} if ( !string.IsNullOrEmpty(item.InnerItem[UrlOnCDN]) ) { return item.InnerItem[UrlOnCDN]; } return mediaUrl; } }
The main method is the GetMediaUrl method. This will check the field where we stored the cdn url, and will render that instead.
As always with Sitecore, we need to create a patch file to let Sitecore know about the hook.
<?xml version="1.0"?> <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/" > <sitecore> <hooks> <hook type="Services.Sitecore.Hooks.MediaProvider, Services.Sitecore"> </hook> </hooks> </sitecore> </configuration>
Now I wanted to write some unit tests for this, and I looked into FakeDb
Using FakeDb I was able to write some tests to make sure that if the CDN url was populated it was returned, or the original Sitecore Media url if it was not
[TestFixture] public class MediaProviderTests { private const string OriginalPrefix = "https://d2llguf9uoxb71.cloudFront.net"; private readonly ID _mediaItemId = new ID("{2A6B753E-28DF-4DA6-9A32-C37B1A03E2F5}"); private const string OriginalMediaUrl = "~/media/myimage.ashx"; private MediaProvider _systemUnderTest; [SetUp] public void Setup() { _systemUnderTest = new MediaProvider(); } [Test] public void MediaProvider_GetMediaUrl_WhenUrlOnCDNFieldIsPopulatedReturnThatValue() { var urlOnCdn = string.Format("{0}/lounge-media/image/ABE-004.jpg", OriginalPrefix); using (var db = new Db()) { db.Add(GetMediaItemForTests(urlOnCdn)); var fakeSite = GetFakeSite(); var mediaItem = db.GetItem(_mediaItemId); using (new SiteContextSwitcher(fakeSite)) { var mediaUrl = _systemUnderTest.GetMediaUrl(OriginalMediaUrl, mediaItem); Assert.That(mediaUrl, Is.EqualTo(urlOnCdn)); } } } [Test] public void MediaProvider_GetMediaUrl_WhenUrlOnCDNFieldIsNotPopulatedReturnOriginalMediaUrl() { using (var db = new Db()) { db.Add(GetMediaItemForTests(string.Empty)); var fakeSite = GetFakeSite(); var mediaItem = db.GetItem(_mediaItemId); using (new SiteContextSwitcher(fakeSite)) { var mediaUrl = _systemUnderTest.GetMediaUrl(OriginalMediaUrl, mediaItem); Assert.That(mediaUrl, Is.EqualTo(OriginalMediaUrl)); } } } private FakeSiteContext GetFakeSite() { return new FakeSiteContext( new StringDictionary { {"name", "website"}, {"database", "web"} }); } private DbItem GetMediaItemForTests(string cdnValue) { var mediaItem = new DbItem("MyImage", _mediaItemId); var urlOnCdnField = new DbField(ID.NewID) { Name = "UrlOnCDN", Value = cdnValue }; mediaItem.Fields.Add(urlOnCdnField); return mediaItem; } }
Now the solution is complete, and when Sitecore renders the html for an image it should now be from the CDN instead of from Sitecore.
[…] Part Two I will update the media presenter so that Sitecore will render the url from the CDN server instead […]