Support SVG files in edit UI

Vote:
 

Inserting svg files in properties marked with UI hunt "Image" makes an nullref error in the logs, and the image looks broken to the editor. Ref: https://support.episerver.com/hc/en-us/requests/291373

SVG files are sometimes the preferred format when displaying logos and such, so this should be supported. It's easy to get thumbnails in the asset pane to show up for SVGs, but the image property itself lacks this support.

#202186
Mar 19, 2019 8:45
Vote:
 

If you are hosting on the DXC this also causes a huge slow down of the overall site performance. 

2019-03-28T16:30:28,Error,ccsl01mstrop34iinte,5fabee,636893874282710141,0,76,159,"Exception calling ImageService RenderImage method (System.NotSupportedException: No imaging component suitable to complete this operation was found. ---> System.Runtime.InteropServices.COMException: The component cannot be found. (Exception from HRESULT: 0x88982F50)
   --- End of inner exception stack trace ---
   at System.Windows.Media.Imaging.BitmapDecoder.SetupDecoderFromUriOrStream(Uri uri, Stream stream, BitmapCacheOption cacheOption, Guid& clsId, Boolean& isOriginalWritable, Stream& uriStream, UnmanagedMemoryStream& unmanagedMemoryStream, SafeFileHandle& safeFilehandle)
   at System.Windows.Media.Imaging.BitmapDecoder.CreateFromUriOrStream(Uri baseUri, Uri uri, Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, RequestCachePolicy uriCachePolicy, Boolean insertInDecoderCache)
   at System.Windows.Media.Imaging.BitmapImage.FinalizeCreation()
   at System.Windows.Media.Imaging.BitmapImage.EndInit()
   at EPiServer.ImageLibrary.ImageLib.LoadBitmapSource(Stream sourceStream, BitmapCreateOptions options)
   at EPiServer.ImageLibrary.ImageService.RenderImage(Byte[] imageBuffer, IEnumerable`1 operations, String mimeType, Single zoomFactor, Int32 jpegQuality)
   at EPiServer.ImageLibrary.ImageServiceClient.RenderImage(Byte[] imageBuffer, IEnumerable`1 operations, String mimeType, Single zoomFactor, Int32 jpegQuality)).",
2019-03-28T16:30:28,Error,ccsl01mstrop34iinte,5fabee,636893874282866660,0,76,159,"EPiServer.Global : Unhandled exception in ASP.NET
System.ArgumentNullException: Value cannot be null.
Parameter name: value
   at System.Web.Caching.CacheEntry..ctor(String key, Object value, CacheDependency dependency, CacheItemRemovedCallback onRemovedHandler, DateTime utcAbsoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, Boolean isPublic, CacheInternal cache)
   at System.Web.Caching.CacheInternal.DoInsert(Boolean isPublic, String key, Object value, CacheDependency dependencies, DateTime utcAbsoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback, Boolean replace)
   at System.Web.Caching.AspNetCache.Add(String key, Object item, CacheInsertOptions options)
   at System.Web.Caching.Cache.Add(String key, Object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback)
   at EPiServer.Cms.Shell.UI.Controllers.Internal.ThumbnailController.Generate(ContentReference contentLink)
   at lambda_method(Closure , ControllerBase , Object[] )
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass24_0.b__0()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
   at System.Web.Mvc.Controller.ExecuteCore()
   at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)
   at EPiServer.Shell.Web.Mvc.ModuleMvcHandler.ProcessController(IController controller)
   at EPiServer.Shell.Web.Mvc.ModuleMvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.<>c__DisplayClass285_0.b__0()
   at System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step)
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)",
#202665
Mar 28, 2019 17:34
Vote:
 

I created a hack to get around this issue.

For previewing thumbs in the asset pane:

[ContentType(GUID = "some guid")]
[MediaDescriptor(ExtensionString = "svg")]
public class VectorImageFile : ImageData
{
    /// <summary>
    /// Gets the generated thumbnail for this awesome vector image.
    /// </summary>
    public override Blob Thumbnail => BinaryData;
}
Hack for properties with UIHint.Image:
/// <remarks>
/// Override to make SVGs pop up in properties with UIHint.Image. --tarjei
/// </remarks>
public class ThumbnailController : Controller
{
    private readonly IContentRepository _contentRepository;
    private readonly IMimeTypeResolver _mimeTypeResolver;
    private readonly ThumbnailManager _thumbnailManager;
 
    public ThumbnailController(
        IContentRepository contentRepository,
        ThumbnailManager thumbnailManager,
        IMimeTypeResolver mimeTypeResolver)
    {
        _contentRepository = contentRepository;
        _thumbnailManager = thumbnailManager;
        _mimeTypeResolver = mimeTypeResolver;
    }
 
    public ActionResult Generate(ContentReference contentLink)
    {
        var realController = new EPiServer.Cms.Shell.UI.Controllers.Internal.ThumbnailController(_contentRepository, _thumbnailManager, _mimeTypeResolver)
        {
            ControllerContext = ControllerContext
        };
        try
        {
            return realController.Generate(contentLink);
        }
        catch (ArgumentNullException)
        {
            if (_contentRepository.TryGet(contentLink, out VectorImageFile content))
            {
                //Error generating thumb for {contentLink}. Use vector {content.Name} directly instead
                Blob binaryData = content.BinaryData;
 
                return File(binaryData.ReadAllBytes(), content.MimeType, content.Name);
            }
 
            throw;
        }
    }
}
It feels very wrong to instantiate an instance of the ThumbnailController from EPiServer’s EPiServer.Cms.Shell.UI.Controllers.Internal namespace, but it is better than displaying broken image previews to the editors.
#202882
Edited, Apr 03, 2019 9:36