Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Andy Cox 31 posts 182 karma points
    Nov 08, 2017 @ 09:40
    Andy Cox
    1

    Empty multi media picker returning {Umbraco.Core.Udi[0]}

    Hi,

    I'm using Ditto to map to my POCOs and have been really pleased with it so far. I have, however, encountered a problem where empty media pickers are returning an error. We are using the media pickers to allow the client to attach various documents to a product. These may sometimes not contain any documents of that type.

    I have a Product page model which has a Technical Documents view model as listed below:

     /// <summary>
    /// The product page model.
    /// </summary>
    public class ProductPageModel : BasePageModel
    {
        /// <summary>
        /// Gets or sets the product technical documents.
        /// </summary>
        [CurrentContentAs]
        public virtual TechnicalDocumentsViewModel TechnicalDocuments { get; set; }
    
        ...
    }
    
    /// <summary>
    /// The product technical documents view model.
    /// </summary>
    public class TechnicalDocumentsViewModel
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="TechnicalDocumentsViewModel"/> class.
        /// </summary>
        public TechnicalDocumentsViewModel()
        {
            this.DataSheets = new List<IPublishedContent>();
            ...
        }
    
        /// <summary>
        /// Gets or sets the product data sheets.
        /// </summary>
        public IEnumerable<IPublishedContent> DataSheets { get; set; }
    
        ...
    }
    

    The error is as follows:

    Cannot bind source type Umbraco.Core.Udi[] to model type System.Collections.Generic.IEnumerable`1[[Umbraco.Core.Models.IPublishedContent, Umbraco.Core, Version=1.0.6471.23325, Culture=neutral, PublicKeyToken=null]].
    

    It seems for empty pickers the value is not being converted. Could this be because I'm using the CurrentContentAs attribute? Or is there another reason why I getting this error?

    Any help would be appreciated.

    Thanks,

    Andy

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Nov 08, 2017 @ 10:53
    Lee Kelleher
    1

    Hi Andy,

    Which version of Umbraco are you using?

    Just to note, I haven't personally used Ditto with the new Udi values yet... so you may well be treading on new ground - prepare yourself for some back & forth on this. :-)

    Having a peek at the Umbraco core source, it looks like the issue is with the property-value-converter for the new MediaPicker2 - specifically these lines...

    https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/src/Umbraco.Web/PropertyEditors/ValueConverters/MediaPickerPropertyConverter.cs#L171-L201

    What's happening is that if the converter can't find any media items, it will return an empty array of Udis. Which would then get passed back to Ditto... and Ditto has no idea what to do with it.

    On a side note, I can't say that I'm happy that the core value-converter is returning wildly different object-types - makes it difficult to know what we should expect.

    Though it looks like someone else raised an issue about it, #U4-10160 + comments on the PR, which got rejected.

    If it returned null, then Ditto could handle that scenario.

    So in order to fix this, either a custom Ditto processor or a generic .NET TypeConverter would need to be created... (or potentially a PR/update to Ditto's UmbracoPicker processor?)

    How are your C# skills? :-)

    Cheers,
    - Lee

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Nov 08, 2017 @ 11:13
    Lee Kelleher
    100

    Just had an alternative idea... by replacing the core's MediaPickerPropertyConverter with your own.

    So you'd have a start-up event to remove the registered value-converter and your own version would then be used.

    Here's some example code...

    using Umbraco.Core;
    using Umbraco.Core.Models.PublishedContent;
    using Umbraco.Core.PropertyEditors;
    using Umbraco.Web.PropertyEditors.ValueConverters;
    
    namespace Our.Umbraco.Ditto.Examples
    {
        public class Bootstrapper: ApplicationEventHandler
        {
            protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
            {
                PropertyValueConvertersResolver.Current.RemoveType<MediaPickerPropertyConverter>();
            }
        }
    
        public class MyMediaPickerPropertyConverter: MediaPickerPropertyConverter
        {
            public override object ConvertSourceToObject(PublishedPropertyType propertyType, object source, bool preview)
            {
                var value = base.ConvertSourceToObject(propertyType, source, preview);
    
                if (value is Udi[])
                {
                    return GetPropertyValueType(propertyType).GetDefaultValue();
                }
    
                return value;
            }
        }
    }
    

    Please note, I haven't tried or tested this... you may have to play around with it to get it to work for your project.

    Cheers,
    - Lee

  • Andy Cox 31 posts 182 karma points
    Nov 10, 2017 @ 09:25
    Andy Cox
    0

    Hi Lee,

    Sorry for the late reply I'm a bit swamped at work at the moment. After reading thorugh the resources you've linked to I have to agree that I think the return type should be the default of the requested type. If the property converter doesn't know how to convert it or it's empty then the default value should be returned. Otherwise my application is going to break!

    I'm still getting to grips with Umbraco, this being my first project, so I wouldn't want to suggest a solution but for the time being creating the custom MediaPickerPropertyConverter has worked a treat.

    Thanks for your time, I'll go with this solution and keep an eye on any changes in the source code.

    Andy

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Nov 10, 2017 @ 10:54
    Lee Kelleher
    0

    Hi Andy,

    I'm still getting to grips with Umbraco, this being my first project...

    Welcome to Umbraco! Despite minor API things like this, it really is an awesome CMS, (that's why I'm still using it for 10 years now).

    (I was a little worried that my initial reply got a bit tech heavy and negative)

    The beauty of open-source is that we can figure these things out as a community... so always feel free to ask any questions you have.

    Cheers,
    - Lee

  • Andy Cox 31 posts 182 karma points
    Nov 10, 2017 @ 10:58
    Andy Cox
    1

    Hey Lee,

    I love the tech, I've been in the industry for 15 years! But I think it's a little early for me to speak with any authority about Umbraco. :)

    I'm certainly enjoying Umbraco so far and will hopefully be able to contribute in the future.

    Thanks again.

    Andy

  • Paciencia Canda 3 posts 71 karma points
    Jan 08, 2018 @ 21:34
    Paciencia Canda
    0

    Hi Andy and Lee,

    Could I maybe get some help with this same issue - my back end skills are not the best so I am having a bit of trouble understanding the solution Lee suggested.

    I initially had a MultimediaPicker field set to the following property on my model:

    [UmbracoPicker]
    public IEnumerable<ImageModel> Images { get; set; }
    

    The ImageModel

        [UmbracoPicker]
        public class ImageModel
        {
              [UmbracoProperty("umbracoWidth")]
                  public virtual int Width { get; set; }
    
                  [UmbracoProperty("umbracoHeight")]
              public virtual int Height { get; set; }
    
              public string Name { get; set; }
    
              public virtual int Id { get; set; }
    
              public virtual string Url { get; set; }
    
              [UmbracoProperty("umbracoBytes")]
              public virtual int Size { get; set; }
    
              [UmbracoProperty("umbracoExtension")]
              public virtual int Type { get; set; }
    
              [UmbracoProperty("type")]
              public string FileType { get; set; }
         }
    

    On a previous version of umbraco ditto (0.10.0) this mapping would work fine and all media items would get converted into ImageModels, however, now I can only get it to work if on my main Model I change the IEnumerable to:

    [UmbracoPicker]
    public IEnumerable<IPublishedContent> Images { get; set; }
    

    Any suggestions to fix this? Or maybe a few more steps to implement the solution proposed? (should I downgrade Umbraco Ditto?)

    Thank you, Paciencia

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Jan 09, 2018 @ 09:57
    Lee Kelleher
    0

    Hey Paciencia,

    Try removing the [UmbracoPicker] attribute from the Images property.

    Since it's on the ImageModel class, then Ditto would use it.

    Let me know if that works for you.

    Cheers,
    - Lee

  • jake williamson 207 posts 872 karma points
    Mar 15, 2018 @ 11:52
    jake williamson
    0

    chiming in a bit late on this one but i've just hit the exact same problem with a new site i'm working on...

    i've created a datatype based on the 'Media Picker' property editor (MediaPicker2) but set it so it can only pick a single image (which according to https://our.umbraco.org/documentation/getting-started/backoffice/property-editors/built-in-property-editors/Media-Picker2 should return a single item of IPublishedContent.

    i'm running my images through a processor as i'm setting the absolute url so my set up is slightly different but this was my 'hack' way round the problem:

    public class ImagePickerAttribute : DittoProcessorAttribute
    {
        private readonly HttpContextBase _httpContext;
        private readonly IModelConverter _modelConverter;
    
        public ImagePickerAttribute()
        {
            _httpContext = DependencyResolver.Current.GetService<HttpContextBase>();
            _modelConverter = DependencyResolver.Current.GetService<IModelConverter>();
        }
    
        public ImagePickerAttribute(HttpContextBase httpContext, IModelConverter modelConverter)
        {
            _httpContext = httpContext;
            _modelConverter = modelConverter;
        }
    
        public override object ProcessValue()
        {
            if (string.Equals(Value?.ToString(), "Umbraco.Core.Udi[]", StringComparison.CurrentCultureIgnoreCase))
            {
                return null;
            }
    
            var image = _modelConverter.ToModel<MediaImageModel>((IPublishedContent)Value);
    
            image.UrlAbsolute = _httpContext?.Request.Url == null ? image.Url : $"{_httpContext.Request.Url.GetLeftPart(UriPartial.Authority)}{image.Url}";
    
            return image;
        }
    }
    

    feels kinda stinky but it does work! what i can't figure out is why umbraco is changing it's return type i.e. if no image is selected you get 'Umbraco.Core.Udi[]' and if an image is selected you get a piece of IPublishedContent?

    tricky...

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Mar 15, 2018 @ 12:08
    Lee Kelleher
    0

    if no image is selected you get 'Umbraco.Core.Udi[]' and if an image is selected you get a piece of IPublishedContent?

    Yup, confusing isn't it?!

    It's all in the value-converter for the MediaPicker2: https://github.com/umbraco/Umbraco-CMS/blob/release-7.9.2/src/Umbraco.Web/PropertyEditors/ValueConverters/MediaPickerPropertyConverter.cs#L171-L201

    Personally, I don't understand the logic behind it. I've tried to have a discussion about it, but unfortunately the conclusion came to it'd would be a breaking-change.

Please Sign in or register to post replies

Write your reply to:

Draft