Copied to clipboard

Flag this post as spam?

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


  • Jamie Pollock 174 posts 853 karma points c-trib
    Sep 21, 2015 @ 13:59
    Jamie Pollock
    0

    IEnumerable<IPublishedContent> to single IPublishedContent - DittoValueResolver or TypeConverter?

    Hey all,
    I'm using a MNTP as a way of filtering content out from a tree picker of a specific document type alias.

    When using the Umbraco Core Property Value Converters this converts the value to a IEnumerable<IPublishedContent>. I'd ideally like a single IPublishedContent then use a TypeConverter to get whatever I need from it.

    Would it be best to use a DittoValueResolver to resolve the value of the achieve this or leave the logic in the TypeConverter?

    It feels like DittoValueResolver is the right way to go. However, I'd want to reuse the logic from an UmbracoPropertyValueResolver for gathering the property value first.

    I love using Ditto but I'm a bit out of the loop when it comes to stuff since Value Resolvers!

    Thanks,
    Jamie

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Sep 21, 2015 @ 14:41
    Lee Kelleher
    0

    Hi Jamie,

    If I understand correctly, you want to get the first (or single) value from the list of MNTP nodes, (IPublishedContent)?

    ValueResolvers would be the way to go.

    To reuse the UmbracoPropertyValueResolver, you'd need to inherit from it... and also inherit from UmbracoPropertyAttribute as both are closely tied together.

    Then with the custom/inherited ValueResolver, you can call the base.ResolveValue(), (of UmbracoPropertyValueResolver), which should return you the IEnumerable<IPublishedContent> value... from that, take the first (or single) value.

    Hope that makes sense?

    Cheers,
    - Lee

  • Jamie Pollock 174 posts 853 karma points c-trib
    Sep 21, 2015 @ 14:59
    Jamie Pollock
    0

    Hey Lee,
    That's exactly what I'd like to do! I think the part I'm struggling with is retaining the functionality of the UmbracoPropertyAttribute whilst also adding the link to my custom resolver.

    Here's what I have so far.

    https://gist.github.com/jamiepollock/fc69044cf874bd838d76

    The code doesn't actually work mind.

    Thanks,
    Jamie

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Sep 21, 2015 @ 15:12
    Lee Kelleher
    100

    Ah! I've just noticed the problem... that the UmbracoPropertyAttribute is tied to the UmbracoPropertyValueResolver, without any way to override it! :-(

    https://github.com/leekelleher/umbraco-ditto/blob/develop/src/Our.Umbraco.Ditto/ComponentModel/Attributes/UmbracoPropertyAttribute.cs#L16

    We'd need to have an overload on the constructor to enable a different ValueResolver to be used.

    e.g.

        public UmbracoPropertyAttribute(Type resolver)
            : base(resolver)
        { }
    

    That way you can have your SinglePublishedContentUmbracoPropertyAttribute class like so...

    public class SinglePublishedContentUmbracoPropertyAttribute
        : UmbracoPropertyAttribute
    {
        public SinglePublishedContentUmbracoPropertyAttribute()
            : base(typeof(SinglePublishedContentValueResolver))
        { }
    }
    

    Of course that means editing Ditto core... feel free to send a PR, or open an issue and I'll find some time to add it in.


    The alternative is to copy the guts of the UmbracoPropertyValueResolver class and use that?

    Cheers,
    - Lee

  • Jamie Pollock 174 posts 853 karma points c-trib
    Sep 21, 2015 @ 15:25
    Jamie Pollock
    1

    Indeed! That's the missing link. :)

    For now the case is fairly simple, my use case is for stuff like specifying a target search page for a search form on a website header or in this case where a jobs form posts too.

    I'm in the midst of moving over to a new laptop so I'll set up an issue on the repo. Cheers, Lee! I thought I was going barmy or doing something wrong.

    Issue created!

    Thanks,
    Jamie

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Sep 21, 2015 @ 15:29
    Lee Kelleher
    1

    It's a case of that we never fully know how those features would be used by developers... it's all progression! :-)

  • Jamie Pollock 174 posts 853 karma points c-trib
    Sep 21, 2015 @ 15:33
    Jamie Pollock
    0

    So long as we're all learning, we all benefit along the way. :)

  • Matt Brailsford 4123 posts 22194 karma points MVP 9x c-trib
    Sep 21, 2015 @ 20:14
    Matt Brailsford
    0

    I'm thinking that a Value Resolver might not be the best option here. Personally I'm thinking that tweaking the property value converter might be the best tact.

    Change the MNTP property value converter to detect if the target type is IEnumerable

    I'm thinking that if all you want to do is wrap the UmbracoPropertyAttribute so as to support all the same options but just change the type coming from the PVC, you should either fix the PVC, or use a TypeConverter?

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Sep 21, 2015 @ 20:43
    Lee Kelleher
    0

    @Jamie - are you using any other PVCs from the "Umbraco Core Property Value Converters" library?

    If not, then as Matt suggests would be a simpler option, as it converts the value early enough in the pipeline.

    On a side-note, I'm still interested in following up on extending the UmbracoPropertyAttribute constructor.

    Cheers,
    - Lee

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Sep 21, 2015 @ 20:58
    Lee Kelleher
    0

    Just in case you need an example of how to de-register an associated PVC.

    protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
    {
        PropertyValueConvertersResolver.Current.RemoveType<MultiNodeTreePickerPropertyConverter>();
    }
    

    ... and the docs for creating your own PVC:

    https://our.umbraco.org/Documentation/Extending/Property-Editors/value-converters

    Cheers,
    - Lee

  • Jamie Pollock 174 posts 853 karma points c-trib
    Sep 22, 2015 @ 08:26
    Jamie Pollock
    0

    @lee, I'm not - so I guess I could go down this route? It feels like a MNTP should convert to single if only one is selected.

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Sep 22, 2015 @ 08:57
    Lee Kelleher
    0

    Hey Jamie, I'm not sure where was best to reply, here or the GitHub issue comments?

    I'll go here :-)

    For the simplest approach, with the least amount of custom code, I'd advise this...

    • Remove the "Umbraco Core Property Value Converters" library, if you're not using it elsewhere, then you don't need it.

    • If all you want is the node's Url property, (taken from here), then try this...

    Create a custom TypeConverter that inherits from DittoPickerConverter, then you can override the ConvertFrom method...

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        var result = base.ConvertFrom(context, culture, value);
    
        if (result is IPublishedContent)
            return ((IPublishedContent)result).Url;
    
        if (result is IEnumerable<IPublishedContent>)
            return ((IEnumerable<IPublishedContent>)result).FirstOrDefault().Url;
    
        return value;
    }
    

    Note: I haven't actually tested this.

    Hope this helps?

    Cheers,
    - Lee

  • Jamie Pollock 174 posts 853 karma points c-trib
    Sep 22, 2015 @ 09:05
    Jamie Pollock
    0

    Hey Lee,
    This makes a lot of sense. I can't think of any other situation where I'd want anything more than the URL so this probably as complex as the code need be.

    As for removing the "Umbraco Core Property Value Converters" project I'll have to see if there is any knock on effect as I'll be using Archetype too.

    Thanks,
    Jamie

  • suzyb 474 posts 932 karma points
    Feb 12, 2016 @ 15:19
    suzyb
    0

    I'm trying to use Lee's TypeConverter code above to map an IPublishedContent returned from MNTP to a custom model however I've come across a stumbling block, a media picker property on the selected MNTP node does not seem to be getting mapped correctly.

    The following is my models and the typeconverter code (snipped for brevity). On the "Open Day" document type I have an MNTP property that allows one "University" node to be selected. The University document type has a media picker property on it to select the university's logo.

    public class OpenDay : PublishedContentModel
    {
        public OpenDay(IPublishedContent content)
            :base(content)
        {}
    
        [TypeConverter(typeof(UniversityTypeConverter))]
        public University AssociatedUniversity { get; set; }
    }
    
    
    public class University : PublishedContentModel
    {
        public University(IPublishedContent content)
            : base(content)
        { }
    
        public IPublishedContent UniversityLogo { get; set; }
    }
    
    
    public class UniversityTypeConverter : DittoPickerConverter
    {
        public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            var result = base.ConvertFrom(context, culture, value);
    
            if (result is IPublishedContent)
                return ((IPublishedContent)result).As<University>() ;
    
            if (result is IEnumerable<IPublishedContent>)
                return ((IEnumerable<IPublishedContent>)result).FirstOrDefault().As<University>();
    
            return value;
        }
    }
    

    When I map the "Open Day" node to the model it maps all the properties of both OpenDay and University except for the UniversityLogo property. Does anyone know why this property is no being set.

    p.s. I have the Umbraco Property Value Converters installed.

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Feb 12, 2016 @ 15:33
    Lee Kelleher
    0

    Hi Suzy,

    OK, to clarify - the other properties of AssociatedUniversity are populated, except for UniversityLogo?

    Just to get it out the way, I'd check for any typos in property-aliases, (sorry, it can happen) :-)

    After that, the "universityLogo" property (media-picker) would contain an ID (int), which I'd assume that the 'Umbraco Property Value Converters' package would be picking up and converting to an IPublishedContent.

    So looking from your code, everything looks to be wired up correctly.

    Let me know if there is a typo ... I'm hoping I'm wrong though.

    Cheers,
    - Lee

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Feb 12, 2016 @ 15:38
    Lee Kelleher
    0

    Thinking about it, you might be able to remove the UniversityTypeConverter all together.

    With Ditto, if a property returns a single or list of IPublishedContent nodes, then it will check if the POCO's target property is a matching type - if not, then Ditto will attempt to map it to the target type.

  • suzyb 474 posts 932 karma points
    Feb 12, 2016 @ 16:37
    suzyb
    0

    Thanks for the prompt reply.

    I initially tried it without the TypeConverter and it didn't work which is why I added it.

    Not sure exactly what I did as I was playing around trying to work out the problem but it seems to work now. I can only think there was some issue with the cache as I didn't change any code, just made sure all the Open Day and University pages had properties set and re-saved them.

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Feb 12, 2016 @ 17:04
    Lee Kelleher
    0

    It should work - at least that's how we wanted it to work - saves developers having to write custom TypeConverters, etc.

    We've got a unit-test to support the scenario...
    https://github.com/leekelleher/umbraco-ditto/blob/master/tests/Our.Umbraco.Ditto.Tests/NestedPublishedContentTests.cs

    ... but I guess other code/packages (real-world things) can come into play. Would be great to have this working for all.


    Anyway, glad that your code is working now. Have a good weekend!

    Cheers,
    - Lee

Please Sign in or register to post replies

Write your reply to:

Draft