Take the community feedback survey now.

K Khan
Dec 10, 2014
  5959
(5 votes)

Using Blobs and CDN both effectively

We have a requirement where Editors can upload images on cloud and use those from website.

We implemented a blob provider to let editors upload and use their images on cloud (cloudinary.com) http://world.episerver.com/code/K-Khan-/Cloudinary-Implementation-in-Blob/

But there were few issues with this implementation, as on presenting the images on website in OpenRead function of provider, we have to download this images in Memory. To read image in memory. That means extra bandwidth usage and using server resources unnecessary. Another option was to redirect to CDN in provider. That means a 302 status and a Error in log files (http://world.episerver.com/Modules/Forum/Pages/Thread.aspx?id=113925). With redirection we have another issue that In Online centre Catalog module was not able to prepare thumbnails.

To deal with these issues we solved it by translating images from globalassets/image.jpg to direct CDN url http://res.cdn.com/account/1537157355371237123.jpg and for Editors we kept the original implementation. This can be useful in many other cases also.

Requirement:
Change <img src="/globalassets/logo.png" alt="" class="" itemprop="logo"> to url in cdn <img src=http://res.cloudinary.com/example.png alt="" class="" itemprop="">

Solution:
I got the help of Johan's solution in some forum post he advised. In initialization module overload ContentRoute.CreatedVirtualPath

ContentRoute.CreatedVirtualPath += this.ReplaceWithCloudUrl;
CatalogRouteHelper.MapDefaultHierarchialRouter(RouteTable.Routes, true);

public void ReplaceWithCloudUrl(object source, UrlBuilderEventArgs eventArgs)
        {
            var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>();

            ////Check if routed content is a IBinaryStorable with a Cloudinary Blob, if so replace url with cdn blob uri      
            object contentReferenceObject;
            if (eventArgs.RouteValues.TryGetValue(RoutingConstants.NodeKey, out contentReferenceObject))
            {
                ContentReference routedContentLink = contentReferenceObject as ContentReference;
                if (!ContentReference.IsNullOrEmpty(routedContentLink))
                {
                    var binaryContent = contentLoader.Get<IContent>(routedContentLink) as IBinaryStorable;
                    if (binaryContent != null)
                    {
                        ////Check that Everyone has Read access before switching to external url
                        ISecurable securable = binaryContent as ISecurable;
                        if (securable != null)
                        {
                            if ((securable.GetSecurityDescriptor().GetAccessLevel(PrincipalInfo.AnonymousPrincipal) & AccessLevel.Read) != AccessLevel.Read)
                            {
                                return;
                            }
                        }

                        var cloudinaryBlob = binaryContent.BinaryData as CloudinaryFileBlob;
                        var httpContext = System.Web.HttpContext.Current.GetRequestContext().HttpContext;
                        if (cloudinaryBlob != null && (!httpContext.Request.Path.ToLower().Contains(SiteConstants.EditingUrlPart.AppSetting())))
                        {
                            imagePath = //CDN Image Path that Blob;
                           
                            UrlBuilder cdnUrlBuilder = new UrlBuilder(imagePath);
                            eventArgs.UrlBuilder.Uri = cdnUrlBuilder.Uri;
                        }
                    }
                }
            }
        }

Dec 10, 2014

Comments

K Khan
K Khan Dec 10, 2014 06:57 PM

Will be happy to hear, how other tech masters resolved this type of issues?

Dec 10, 2014 08:40 PM

This is awesome. This is how blobs should be served!

Frederik Vig
Frederik Vig Dec 10, 2014 09:39 PM

We´ve done similar, but instead we´ve used the IIS extension URL Rewrite to rewrite ouput URLs to the CDN version. The CDN adds the image cached, if it didn´t have the image it would contact EPiServer and get the right image, then put it in it´s cache and serve it to the end user. Like a reverse proxy basically.

Frederik

Please login to comment.
Latest blogs
Optimizely CMS Mixed Auth - Okta + ASP.NET Identity

Configuring mixed authentication and authorization in Optimizely CMS using Okta and ASP.NET Identity.

Damian Smutek | Oct 27, 2025 |

Optimizely: Multi-Step Form Creation Through Submission

I have been exploring Optimizely Forms recently and created a multi-step Customer Support Request Form with File Upload Functionality.  Let’s get...

Madhu | Oct 25, 2025 |

How to Add Multiple Authentication Providers to an Optimizely CMS 12 Site (Entra ID, Google, Facebook, and Local Identity)

Modern websites often need to let users sign in with their corporate account (Entra ID), their social identity (Google, Facebook), or a simple...

Francisco Quintanilla | Oct 22, 2025 |

Connecting the Dots Between Research and Specification to Implementation using NotebookLM

Overview As part of my day to day role as a solution architect I overlap with many clients, partners, solutions and technologies. I am often...

Scott Reed | Oct 22, 2025