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):
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.
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.
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
}
}
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:
This class is mapped from another class that has a collection of
IWidget
:The
DittoMixedArchetypeAttribute
is just a multi-attribute that is composed ofDittoArchetypeAttribute
andDittoDocTypeFactoryAttribute
. SincePickedWidget
implementsWidget
and sinceWidget
implementsIWidget
, any Archetype fieldset with an alias ofPickedWidget
causes thePickedWidget
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 thatUmbracoPropertyAttribute
can't be applied to the same property twice. This is because you haven't marked that attribute asAllowMultiple
. Here's an example of how you'd do that (this would go on the class for theUmbracoPropertyAttribute
):To work around that, I temporarily created
MyUmbracoPropertyAttribute
(using the same code that is found inUmbracoPropertyAttribute
). However, that was returning null fromProcessValue
. 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#L106It is getting the
IPublishedContent
from the context rather than fromthis.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 fromProcessValue
, then the next processor uses the result of that as input to further process things. However, since this particular processor seems to be ignoring thatValue
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 theUmbracoPropertyAttribute
for troubleshooting purposes. Here's a commented version of the above class to indicate exactly what I'm trying to accomplish with each processor: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.
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
Thanks, Matt! Seems to have worked once updated the NuGet package. Here's the code for reference:
is working on a reply...