Copied to clipboard

Flag this post as spam?

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


  • Nicholas Westby 2054 posts 7100 karma points c-trib
    Jul 19, 2016 @ 18:22
    Nicholas Westby
    0

    Multiple Processor Chaining Issues

    I'm encountering a number of issues, so maybe I am misunderstanding how processor chaining is supposed to work. I'll run it by you. If my understanding is correct, this might require several bug reports.

    First of all, here's the property I'm trying to map:

    public class PickedWidget : Widget
    {
        [UmbracoProperty]
        [UmbracoPicker]
        [DittoFirstItem]
        [UmbracoProperty(propertyName: "mainContent")] //TODO: Should be [DittoArchetype(propertyName:"mainContent")]
        [DittoDocTypeFactory]
        [DittoFirstItem]
        public IWidget PickedItem { get; set; }
    
    }
    

    This class is mapped from another class that has a collection of IWidget:

    public class Typical
    {
        [DittoMixedArchetype]
        public IEnumerable<IWidget> MainContent { get; set; }
    }
    

    The DittoMixedArchetypeAttribute is just a multi-attribute that is composed of DittoArchetypeAttribute and DittoDocTypeFactoryAttribute. Since PickedWidget implements Widget and since Widget implements IWidget, any Archetype fieldset with an alias of PickedWidget causes the PickedWidget class to be instantiated.

    As you can see from the attributes above the PickedItem property, I'm attempting to make heavy use of chaining processors. The first issue I'm running into is that UmbracoPropertyAttribute can't be applied to the same property twice. This is because you haven't marked that attribute as AllowMultiple. Here's an example of how you'd do that (this would go on the class for the UmbracoPropertyAttribute):

    [AttributeUsage(validOn: AttributeTargets.Property, AllowMultiple = true)]
    

    To work around that, I temporarily created MyUmbracoPropertyAttribute (using the same code that is found in UmbracoPropertyAttribute). However, that was returning null from ProcessValue. The reason for that seems to be because of this line: https://github.com/leekelleher/umbraco-ditto/blob/81e60f123df69a6c45bba2036a7ea9418bb26c7a/src/Our.Umbraco.Ditto/ComponentModel/Processors/UmbracoPropertyAttribute.cs#L106

    It is getting the IPublishedContent from the context rather than from this.Value. That confuses me, because as far as I'm aware the processors don't actually change the context (I could be wrong about that). I thought the idea was that you have a processor return some value from ProcessValue, then the next processor uses the result of that as input to further process things. However, since this particular processor seems to be ignoring that Value entirely, the chaining doesn't seem to work.

    By the way, I put that "TODO" comment because I was originally trying to use the DittoArchetypeAttribute, but I ran into issues so I reverted to the UmbracoPropertyAttribute for troubleshooting purposes. Here's a commented version of the above class to indicate exactly what I'm trying to accomplish with each processor:

    public class PickedWidget : Widget
    {
        // First, I'm getting the content node specified in the "PickedItem" property on this Archetype fieldset.
        [UmbracoProperty]
        // Next, I'm getting the IPublishedContent corresponding to that ID.
        [UmbracoPicker]
        // Next, I'm getting the first IPublishedContent in that collection.
        [DittoFirstItem]
        // Now, I'm attempting to get the ArchetypeModel from the "mainContent" property on the IPublishedContent. This is failing.
        [UmbracoProperty(propertyName: "mainContent")] //TODO: Should be [DittoArchetype(propertyName:"mainContent")]
        // Next, I'm attempting to map the Archetype fieldsets in the ArchetypeModel to particular POCO classes.
        [DittoDocTypeFactory]
        // Since the above collection will only have one item, I'm getting the first item from that collection. Of course, I never actually got this far.
        [DittoFirstItem]
        public IWidget PickedItem { get; set; }
    }
    

    Hopefully that makes sense. If I were encountering just one issue, this would be easier to explain. However, since I'm encountering a number of issues, it muddles things a bit.

  • Matt Brailsford 4123 posts 22194 karma points MVP 9x c-trib
    Jul 20, 2016 @ 08:11
    Matt Brailsford
    101

    Hi Nic,

    I've made a couple of changes in Ditto to allow UmbracoPropertyAttribute to be used multiple times, as well as having it grab the IPublishedContent from Value rather than the context. You can grab the nightly build from the build server here https://ci.appveyor.com/project/leekelleher/umbraco-ditto/build/artifacts or on myget here https://www.myget.org/gallery/umbraco-ditto

    I've added a unit test to prove this functionality here https://github.com/leekelleher/umbraco-ditto/blob/develop/tests/Our.Umbraco.Ditto.Tests/ChainedProcessorTests.cs#L156

    In theory then with this build I think what you are trying to do should work, however the only other thing I would suggest you do is set the "Order" property of all your attributes as you can't rely on the order of attributes being fetched being the same as the order they are defined in, hence why we have the Order property.

    Hope this helps

    Matt

  • Nicholas Westby 2054 posts 7100 karma points c-trib
    Jul 20, 2016 @ 15:58
    Nicholas Westby
    0

    Thanks, Matt! Seems to have worked once updated the NuGet package. Here's the code for reference:

    namespace Wiski.App.Mapping.Models.Widgets
    {
    
        // Namespaces.
        using Common;
        using Interfaces;
        using Our.Umbraco.Ditto;
        using Processors;
        using System.Web.Mvc;
        using Utility;
    
        /// <summary>
        /// A picked widget (i.e., this widget allows a user to create a content node containing a widget
        /// that is then picked by this widget from another content node).
        /// </summary>
        public class PickedWidget : Widget
        {
    
            #region Properties
    
            /// <summary>
            /// The picked widget.
            /// </summary>
            /// <remarks>
            /// Named "PickedItem" rather than just "Item" due to a Ditto bug: https://github.com/leekelleher/umbraco-ditto/issues/181
            /// </remarks>
            [UmbracoProperty(Order = 1)]
            [UmbracoPicker(Order = 2)]
            [DittoFirstItem(Order = 3)]
            [DittoArchetype(propertyName:"mainContent", Order = 4)]
            [DittoDocTypeFactory(Order = 5)]
            [DittoFirstItem(Order = 6)]
            public IWidget PickedItem { get; set; }
    
            #endregion
    
            #region Methods
    
            /// <summary>
            /// Renders the picked widget.
            /// </summary>
            /// <param name="helper">
            /// The HTML helper.
            /// </param>
            /// <returns>
            /// The rendered Angular directive.
            /// </returns>
            public override string Render(HtmlHelper helper)
            {
                return WidgetUtility.ConvertWidgetToDirective(PickedItem, helper);
            }
    
            #endregion
    
        }
    
    }
    
Please Sign in or register to post replies

Write your reply to:

Draft