Try our conversational search powered by Generative AI!

How do I get images fetched via a custom Content Provider to get routed correctly?



I am trying to get external image content to work in Optimizely, but have problems piecing everything together.

I have implemented a ContentProvider that fetches images and folders from the external API and transforms them to custom content types derived from ImageData and ContentFolder respectively. After the images are fetched they are stored as Blobs using a quick and dirty BlobProvider that inherits from FileBlobProvider that saves the image data under App_data.

So far so good. The provider is mounted under GlobalAssets and the folder structure and media items are rendered as you would expect in both the Media tab and a custom component under its own tab (using epi-cms/compnent/Media dojo thingie.) I can drag and drop images to page properties (ContentReference with UIHint.Image) and to Tiny editors and they are displayed as expected both in their full form and as thumbnails in Preview.

The problem starts when the page is published and viewed on site. The images are now 404 not found. Probably a routing issue, so i added logging to the IContentUrlResolverEvents and IContentUrlGeneratorEvents to see what was happening. I noticed that all my image URLs were resolved to the root folder of the content provider, so the next logical step was to implement an IPartialRouter to handle the routing of those URLs.

Now the content gets resolved correctly, I can see that it is my custom Image content type and that is has a correct Blob reference that represents a valid image that exists on disk.

But it still 404s. And now the images in Edit/Preview have stopped working too. I just can't figure out which part of the framework is responsible for looking at the - in my opinion - perfectly valid content and deciding that "Nope, no image data here, let's return a 404."

I am probably missing something obvious, but I can't see what.

URLs that work in edit mode without a custom partial router:

  • /EPiServer/CMS/Thumbnail/Generate/?contentLink=42__mycontentprovider&epi.preventCache=1678264039926
  • /EPiServer/CMS/Content/globalassets/en/mycontentproviderroot/folder/filename.png,,42__mycontentprovider/Thumbnail?epieditmode=False?1678264161539

Not working:

  • /globalassets/mycontentproviderroot/folder/filename.png (gets routed to the root folder but still does not work after partial router points it to the correct content)
Mar 08, 2023 12:10
Minesh Shah (Netcel) - Mar 08, 2023 19:35
Might sound too obvious but have you checked the permissions to the folder also are the assets definitely published ?

Further too my comment regarding Publish Status and Permissions, can you check you are not missing a segment in the URL ? 

Edit mode will be able to get the asset as it also has the ID in URL i.e. ,,42

Mar 08, 2023 19:46

I built similar content provider and widget to pull folders and images from external source and was appearing in media pane and can drag and drop. But in your case, when you render image, are you using image url (src) from Optimizely created blobs or directly use image url from external source?

In my case, as I am using Content Provider and images are stored in exteranl system, I was returing and using exteranl url for image and rendering and was not creating blobs in app_data in Optimizely.

Also, I was storing exteranl source image url in Optimizely Media content type url and refering same to render image.

For edit/preview issue, you may use below:

   // asset preview controller
        Inherited = true,
        TemplateTypeCategory = TemplateTypeCategories.MvcController, //Required as controllers for blocks are registered as MvcPartialController by default
        Tags = new[] { RenderingTags.Preview, RenderingTags.Edit },
        Default = true,
        AvailableWithoutTag = false)]
    public class CustomAssetController : ActionControllerBase, IRenderTemplate<CustomAsset>
        public ActionResult Index(CustomAsset currentContent)
            return View("Preview", currentContent);

I hope this helps.

Let me know in case you need more clarity or walkthorugh how I built it.

Edited, Mar 10, 2023 9:10

Thank you for your input.

In my case the images are behind an API without external URLs, so I have to fetch them and store them in whichever Blob provider is configured and add some custom stuff to keep things synced.

I ended up using a custom IContentRouteRegister class to register a route "root" for the content and a custom ASP.NET middleware to handle those requests.

This works, but it may not be "best practice" in Optimizely.

Mar 13, 2023 15:58
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.