• About this blog
  • About me
  • Contact
Sitecore XperiencesThe things I've seen as a Sitecore Professional
  • About this blog
  • About me
  • Contact
Menu
  • About this blog
  • About me
  • Contact
  • Language specific MediaProvider breaking icons at Media Library

    February 14, 2017 Rodrigo Peplau 2

    UPDATE: Kamruz Jaman has contributed with a comment for a simpler, less intrusive and more generalist solution:  Inside the GetMediaUrl method of your custom MediaProvider, check for the “Thumbnail” property of your MediaUrlOptions parameter. If it is true, make your code fall back to the base, such as:

    if (mediaOptions.Thumbnail)
    return base.GetMediaUrl(mediaItem, mediaOptions);

    During an upgrade from Sitecore 6.5 to Sitecore 8.1 one issue were noticed at the Media Library: when a Media Item is uploaded, the icon appears broken.

    Broken Icon

    A custom MediaProvider is used at this build to modify the way Sitecore generates Media Item urls. All it does is to add the language at beginning of the media URL so we can have language-specific media items. This is important to allow the same Media Item (etc: an image or PDF) to be served in multiple languages.

    Root cause

    When a media item is uploaded to the Media Library, Sitecore will fill the “Icon” field with the URL of the media item itself. Because of the custom MediaProvider, language is being added to the beginning of the generated URL. Apparently that was not a problem in Sitecore 6.5, but things seems to have changed at Sitecore 8.

    Technical explanation by Sitecore

    A Support Ticket #476256 were created to allow further investigation from Sitecore on this issue. According to the technical team:

    “The behavior you reported is expected as tree node icons are rendered by Sitecore.Shell.Applications.ContentManager.Sidebars.Tree.RenderIcon(Item item) method which does not use language definition, embedded to URL, to resolve item language. So when the Icon field contains URL with language definition embedded, it breaks the method functionality and leads to incorrect resolution of the item’s icon.

    When you have versioned media item, the icon is rendered for specific language automatically even when language is not specified deliberately. For instance, if you have media item with two language versions and different images for each language, and use -/media/ItemGUID.ashx?h=16&thn=1&w=16 string in the Icon field, language specific icon will be rendered when you switch the language in the Content Editor.”

    This explains the causes but doesn’t fix the issue: how can we skip or bypass the custom MediaProvider, avoiding the language to be added to the URL when the “Icon” field is filled?

    Solution

    In order to fix that we will need to extend and override the Sitecore.Resources.Media.Media class, responsible for the upload and update of metadata when a Media Item is uploaded to the Media Library, then modify all Media Types to use your class instead of the original.

    Step 1 – Extend the Media class

    This is going to be responsible for removing the language from the URL when a Media Item is uploaded. In bold you see the code responsible for that, rest is basically native code to ensure compliance with default Sitecore behavior.

    using Sitecore;
    using Sitecore.Configuration;
    using Sitecore.Data.Items;
    using Sitecore.Data.Proxies;
    using Sitecore.Diagnostics;
    using Sitecore.Resources.Media;
    using Sitecore.SecurityModel;
    
    namespace CustomMediaProvider
    {
      public class Media : Sitecore.Resources.Media.Media
      {
        public override Sitecore.Resources.Media.Media Clone()
        {
          return new Media();
        }
    
        public override void UpdateMetaData(MediaStream mediaStream)
        {
          Assert.ArgumentNotNull(mediaStream, "mediaStream");
          var innerItem = MediaData.MediaItem.InnerItem;
          if (!innerItem.Paths.IsMediaItem) return;
          using (new EditContext(innerItem, SecurityCheck.Disable))
          {
            innerItem["extension"] = mediaStream.Extension;
            innerItem["mime type"] = mediaStream.MimeType;
            innerItem["size"] = mediaStream.Length.ToString();
            if (Settings.Media.AutoSetAlt)
            {
              innerItem["Alt"] = innerItem.Name;
            }
            var shellOptions = MediaUrlOptions.GetShellOptions();
            shellOptions.Thumbnail = true;
            shellOptions.Height = 0x10;
            shellOptions.Width = 0x10;
            var realItem = ProxyManager.GetRealItem(innerItem, true);
            // CODE ADDED TO REMOVE LANGUAGE FROM URL WHILE UPLOADING
            var iconUrl = MediaManager.GetMediaUrl(realItem, shellOptions);
            var prefix = "/" + Context.Language.Name + "/";
            if (iconUrl.StartsWith(prefix)) iconUrl = iconUrl.Replace(prefix, "");
            innerItem.Appearance.Icon = iconUrl;
          }
        }
      }
    }

    Step 2 – Register the Media class to all Media Types

    This is the painful part: we will need to register our class to every Media Type we want to cover. There is no easy way for that other than adding a node for each Media Type, paying attention to the correct way for patching that specific node (some nodes may have a Media class already defined and thus needs correct patching, others don’t).

    <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
     <sitecore>
     <mediaLibrary>
     <!-- This is our Custom MediaProvider causing all the trouble -->
     <mediaProvider>
     <patch:attribute name="type">CustomMediaProvider.MediaProvider,CustomMediaProvider</patch:attribute>
     </mediaProvider>
     <!-- And here goes our custom Media class being attached to several Media Types -->
     <mediaTypes>
     <mediaType name="Any" extensions="*">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider" patch:instead="*[@type='Sitecore.Resources.Media.Media, Sitecore.Kernel']"/>
     </prototypes>
     </mediaType>
     <mediaType name="AVI video" extensions="avi">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider"/>
     </prototypes>
     </mediaType>
     <mediaType name="Windows Bitmap image" extensions="bmp, dib">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider" patch:instead="*[@type='Sitecore.Resources.Media.ImageMedia, Sitecore.Kernel']"/>
     </prototypes>
     </mediaType>
     <mediaType name="Flash" extensions="swf">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider" patch:instead="*[@type='Sitecore.Resources.Media.SwfMedia, Sitecore.Kernel']"/>
     </prototypes>
     </mediaType>
     <mediaType name="Flash video" extensions="flv">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider"/>
     </prototypes>
     </mediaType>
     <mediaType name="GIF image" extensions="gif">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider" patch:instead="*[@type='Sitecore.Resources.Media.ImageMedia, Sitecore.Kernel']"/>
     </prototypes>
     </mediaType>
     <mediaType name="HTML" extensions="htm,html,stm">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider"/>
     </prototypes>
     </mediaType>
     <mediaType name="JPEG image" extensions="jpg, jpeg, jpe, jfif">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider" patch:instead="*[@type='Sitecore.Resources.Media.ImageThumbnailGenerator, Sitecore.Kernel']"/>
     </prototypes>
     </mediaType>
     <mediaType name="MP3" extensions="mp3">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider" patch:instead="*[@type='Sitecore.Resources.Media.Mp3Media, Sitecore.Kernel']"/>
     </prototypes>
     </mediaType>
     <mediaType name="MP4 video" extensions="mp4">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider"/>
     </prototypes>
     </mediaType>
     <mediaType name="PDF file" extensions="pdf">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider"/>
     </prototypes>
     </mediaType>
     <mediaType name="PNG image" extensions="png">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider" patch:instead="*[@type='Sitecore.Resources.Media.ImageMedia, Sitecore.Kernel']"/>
     </prototypes>
     </mediaType>
     <mediaType name="SVG image" extensions="svg">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider" patch:instead="*[@type='Sitecore.Resources.Media.SvgMedia, Sitecore.Kernel']"/>
     </prototypes>
     </mediaType>
     <mediaType name="QuickTime movie" extensions="mov, qt">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider"/>
     </prototypes>
     </mediaType>
     <mediaType name="TIFF image" extensions="tiff, tif">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider" patch:instead="*[@type='Sitecore.Resources.Media.ImageMedia, Sitecore.Kernel']"/>
     </prototypes>
     </mediaType>
     <mediaType name="Zip file" extensions="zip">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider" patch:instead="*[@type='Sitecore.Resources.Media.ZipMedia, Sitecore.Kernel']"/>
     </prototypes>
     </mediaType>
     <mediaType name="Video for Adobe Flash Player" extensions="f4v">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider"/>
     </prototypes>
     </mediaType>
     <mediaType name="Windows Media video" extensions="WMV">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider"/>
     </prototypes>
     </mediaType>
     <mediaType name="Word document" extensions="doc">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider"/>
     </prototypes>
     </mediaType>
     <mediaType name="Word 2007 document" extensions="docx">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider"/>
     </prototypes>
     </mediaType>
     <mediaType name="PPTX File" extensions="pptx">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider"/>
     </prototypes>
     </mediaType>
     <mediaType name="PPT File" extensions="ppt">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider"/>
     </prototypes>
     </mediaType>
     <mediaType name="XLSX File" extensions="xlsx">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider"/>
     </prototypes>
     </mediaType>
     <mediaType name="XLS File" extensions="xls">
     <prototypes>
     <media type="CustomMediaProvider.Media, CustomMediaProvider"/>
     </prototypes>
     </mediaType>
     </mediaTypes>
     </mediaLibrary>
     </sitecore>
    </configuration>

    Categories: Bug fixing, Development, Support Ticket, Upgrades

    ERROR [Content Testing]: Cannot find PhantomJS executable at ' (...) /data/tools/phantomjs/phantomjs.exe'. Aborting screenshot generation. Richtext Editor - Table Properties adds cells to the table

    2 thoughts on “Language specific MediaProvider breaking icons at Media Library”

    • Kamruz Jaman says:
      February 14, 2017 at 5:17 pm

      Another option would have been to check if the request was for a thumbnail (the ?thn=1 part of the stored Icon url) and if so ignore your custom code to generate the Media URLs. This is what I ended up doing for some code I wrote:

      https://github.com/jammykam/Sitecore-CloudMediaLibrary/blob/master/src/FS.MediaLibrary.CloudStorage/Media/MediaProvider.cs#L22

      Reply
      • Rodrigo Peplau says:
        February 23, 2017 at 5:59 pm

        Great point Kamruz, I’ve just tested you approach and it also made the trick.

        In fact your approach is actually better as it is less intrusive and works in more cases, such as when the Attachment field renders.

        I am updating the article with a message at the top suggesting your solution as a better response. Thank you very much!

        Reply

    Leave a Reply Cancel reply

    Your email address will not be published. Required fields are marked *

      Am Not Spammer

    You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Proudly 8x Sitecore MVP (2016-2023) MVP 2016-2023

Localization

Recent Posts

  • Error enabling GraphQL IDE with XM Cloud
  • Meet MVPinny: the AI-Powered Sitecore Assistant
  • Content generation with Sitecore Connect and ChatGPT
  • XM Cloud Starter Kit with Content Hub Integration
  • Meet the (Brand new) Advanced Powershell Packaging Features

Recent Comments

  • navan on Meet MVPinny: the AI-Powered Sitecore Assistant
  • Adriana on Content generation with Sitecore Connect and ChatGPT
  • NAVAN on Automatic Sitecore NuGet upgrades with Powershell
  • Hedipo S Menezes on Corey Peplau wrote this - WFFM conflict with Unity DI and a lesson on how Sitecore community is so amazing
  • Rodrigo Peplau on ERROR [Content Testing]: Cannot find PhantomJS executable at ' (...) /data/tools/phantomjs/phantomjs.exe'. Aborting screenshot generation.

Archives

  • December 2023
  • November 2023
  • August 2023
  • July 2023
  • January 2023
  • February 2022
  • December 2021
  • November 2021
  • March 2021
  • July 2020
  • February 2020
  • September 2019
  • July 2019
  • April 2019
  • March 2019
  • December 2018
  • February 2018
  • January 2018
  • November 2017
  • September 2017
  • August 2017
  • July 2017
  • March 2017
  • February 2017
  • November 2016
  • September 2016
  • August 2016
  • July 2016
  • April 2016
  • November 2015
  • September 2015
  • July 2015
  • April 2015
  • March 2015
  • February 2015

Categories

  • Actions
  • Active Directory
  • Analytics
  • Architecture
  • Bug fixing
  • CDP/Personalize
  • ChatGPT
  • Content Edition Experience
  • Content Hub
  • Continuous Integration
  • Dev
  • Development
  • Environments
  • Experience Editor
  • Experience Forms
  • Front-end
  • Health Check builds
  • Helix
  • How To
  • LDAP
  • MVP
  • MVP Summit
  • Phantom JS
  • Powershell
  • QA
  • Richtext Editor
  • Rules
  • Security Provider
  • SIF
  • Sitecore 9
  • Sitecore API
  • Sitecore Community
  • SItecore Connect
  • Sitecore Modules
  • Sitecore Rocks
  • Sitecore Rule Processor
  • Sitecore Symposium
  • SPE
  • SPEAK
  • SUG
  • Support Ticket
  • TDS
  • Team City
  • Uncategorized
  • Upgrades
  • Visual Studio
  • WFFM
  • Workflow
  • XConnect
  • xDB
  • XM Cloud

Meta

  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org

Recent Posts

  • Error enabling GraphQL IDE with XM Cloud
  • Meet MVPinny: the AI-Powered Sitecore Assistant
  • Content generation with Sitecore Connect and ChatGPT
  • XM Cloud Starter Kit with Content Hub Integration
  • Meet the (Brand new) Advanced Powershell Packaging Features
  • Rodrigo Peplau wins his 8th Sitecore MVP Award
  • Glossary: Sitecore CDP vs Sitecore XP
  • ReplaceHTML doesn’t work in Web Experiences with Sitecore Personalize
  • Sitecore Personalize: Difference between “Experiences” and “Experiments”
  • Automatic Sitecore NuGet upgrades with Powershell

Tag Cloud

    Architecture Automation Continuous Integration Debugging Development Environments Hackathon How To PhantomJS Powershell Server Roles TDS Team City Team Development for Sitecore XConnect

Pages

  • About this blog
  • About me
  • Contact

Search

Copyright © 2015 Rodrigo Peplau Theme created by PWT. Powered by WordPress.org