Copied to clipboard

Flag this post as spam?

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


  • Jay 409 posts 635 karma points
    Mar 18, 2016 @ 15:11
    Jay
    0

    Model Builder with Nested Content

    Hey Lee,

    I'm trying out the new V7.4.1 with the ModelsBuilder but it picks up Nested Content as object instead of IEnumerable

    Can you point me to the right direction on how I should create a converter to it will return the right type?

    Btw i'm using Nested Content 0.2.0 from Nuget

    Thanks

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

    Hi JLon,

    Unfortunately I haven't had opportunity to try out ModelsBuilder with Nested Content yet. I don't know enough about it to offer any useful advice.

    Hopefully someone who has experience with ModelsBuilder will jump in on this thread.

    Cheers,
    - Lee

  • David Peck 687 posts 1863 karma points c-trib
    Mar 18, 2016 @ 15:24
    David Peck
    1

    Weird, I was just about to post with the same issue.

    The solution I have so far is to use the Visual Studio Custom Tool and then manually cast the object.

    It's a pain in the arse though. I assume it is something to do with the detached models or something like that that I've seen discussed before.

    [IgnorePropertyType("usefulLinks")]
    [IgnorePropertyType("navigation")]
    public partial class Footer
    {
    
        public IEnumerable<NavigationItem> UsefulLinks
        {
            get
            {
                var usefulLinks = this.GetPropertyValue<IEnumerable<IPublishedContent>>("usefulLinks");
                return usefulLinks.Select(x => new NavigationItem(x));
            }
        }
    
        public IEnumerable<NavigationListWithTitle> Navigation
        {
            get
            {
                var navigation = this.GetPropertyValue<IEnumerable<IPublishedContent>>("navigation");
                return navigation.Select(x => new NavigationListWithTitle(x));
            }
        }
    }
    
  • Jeroen Breuer 4908 posts 12265 karma points MVP 4x admin c-trib
    Mar 18, 2016 @ 15:29
    Jeroen Breuer
    0

    Hello,

    This example uses an old version of the models builder, but it should still work the same. You need to create a partial class and implement the property there yourself: https://gist.github.com/jbreuer/0a5996e5e6bf881ce847#file-gistfile1-cs-L28

    A cool thing is that the IPublishedContent you get from Nested Content can also be converted to a strongly typed model because it's based on a document type which also has a model. More info about that in this blog: http://24days.in/umbraco/2015/multilingual-vorto-nested-content/

    Jeroen

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Mar 18, 2016 @ 15:32
    Lee Kelleher
    0

    Ahhh, it's suddenly come back to me... we have an (unreleased) fix for this.

    See these GitHub issue + pull-request:

    https://github.com/leekelleher/umbraco-nested-content/issues/49

    https://github.com/leekelleher/umbraco-nested-content/pull/51

    If you wanted to use the latest (bleeding-edge) development version of Nested Content, you can grab the package file from here:

    https://ci.appveyor.com/project/leekelleher/umbraco-nested-content/build/0.2.0.69/artifacts

    It should be pretty stable, but usual risks/warnings apply.

    Cheers,
    - Lee

  • Jay 409 posts 635 karma points
    Mar 18, 2016 @ 15:37
    Jay
    0

    aha lee, that seems to have worked. will the fix be release anytime soon as one of the latest package?

  • Jay 409 posts 635 karma points
    Mar 18, 2016 @ 15:38
    Jay
    0

    Jeroen, i'll try out the partial class as well too.

    You guys are legend :)

  • David Peck 687 posts 1863 karma points c-trib
    Jul 11, 2016 @ 17:07
    David Peck
    0

    Lee: Thanks for releasing 0.3.0 with the better ModelsBuilder support in it.

    The IPublishedContent objects that it returns are still not the ModelsBuilder IPublishedContent wrapper objects though. Is there any way to achieve this so that you can just do:

    MyModel.MyNestedContentProperty.OfType<MyOtherModel>();
    

    rather than having to create a partial class of MyModel to override the MyNestedContentProperty property and call the constructor of MyOtherModel for each IPublishedContent in MyNestedContentProperty? e.g.

    return this.MyNestedContentProperty.Select( c => new MyOtherModel(x));
    
  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Jul 11, 2016 @ 17:21
    Lee Kelleher
    0

    Hi David,

    Honestly, I have no idea. I still haven't got around to using ModelsBuilder yet, so I'm not in a position to make suggestions on its usage.

    For NestedContent, we literally added this line: ref

    [PropertyValueType(typeof(IEnumerable<IPublishedContent>))]
    

    Which meant that ModelsBuilder would use that type for the property.

    I'm not sure how OfType() extension would work in that context?

    If you think there is something missing that we need to add to Nested Content to support this scenario? We're all ears. Otherwise I don't know what to suggest.

    Cheers,
    - Lee

  • David Peck 687 posts 1863 karma points c-trib
    Jul 11, 2016 @ 20:01
    David Peck
    1

    No worries Lee. The attribute addition is very welcome. It's not a big deal to work around it, I'm just being anal.

    It seems that the content factory that the Models Builder comes with, isn't used for your detached content gubbins. I guess with it going in to the core it may be useful to resolve at some point. If only there was a package where you could create a model with an extension method .

    e.g. myContent.As<MyModel>()
    

    That would be cool ;-)

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Jul 11, 2016 @ 20:03
    Lee Kelleher
    1

    Yup, Ditto! :-P

  • Jeremy Pyne 106 posts 246 karma points MVP c-trib
    Oct 31, 2016 @ 20:57
    Jeremy Pyne
    0

    You can manually create ProeprtyConverters for your custom types that map directly to strong typed models. There is an example(though its for a different plugin).

    Property Converter:

    namespace Proteus.DataTypeModels.PropertyConverters
    {
        [PropertyValueType(typeof(IEnumerable<Carousel>))]
        [PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
        public class CarouselPropertyConverter : PropertyValueConverterBase
        {
            private readonly string PropertyEditorAlias = "NestedDataType";
            private readonly int[] DataTypeId  = { 1089 };
    
            public override bool IsConverter(PublishedPropertyType propertyType)
            {
                return propertyType.PropertyEditorAlias.Equals(PropertyEditorAlias) && DataTypeId.Contains(propertyType.DataTypeId);
            }
    
            public override object ConvertSourceToObject(PublishedPropertyType propertyType, object source, bool preview)
            {
                if (source == null)
                {
                    return null;
                }
    
                try
                {
                    return Carousel.Parse((string)source);
                }
                catch
                {
                    return null;
                }
    
            }
        }
    }
    

    Model:

    namespace Proteus.DataTypeModels
    {
        public class Carousel : JObject
        {
    
            public Carousel(JObject data)
                :base(data)
            { }
    
            public new static IEnumerable<Carousel> Parse(string json)
            {
                return JArray.Parse(json).Children().Select(s => new Carousel((JObject)s));
            }
    
            /// <summary>
            /// Full Image: Banner Image to use on desktop devices.
            /// </summary>
            public IPublishedContent FullSrc
            {
                get
                {
                    return this["FullSrc"] == null || String.IsNullOrEmpty(this["FullSrc"].Value<string>()) ? null : UmbracoContext.Current.MediaCache.GetById(this["FullSrc"].Value<int>());
                }
            }
    
            /// <summary>
            /// Small Image: Smaller image to use on tablet or mobile devices.
            /// </summary>
            public IPublishedContent SmallSrc
            {
                get
                {
                    return this["SmallSrc"] == null || String.IsNullOrEmpty(this["SmallSrc"].Value<string>()) ? null : UmbracoContext.Current.MediaCache.GetById(this["SmallSrc"].Value<int>());
                }
            }
    
            /// <summary>
            /// Alt Text: Alt text to add to the images.  If not specified the image name will be used instead.
            /// </summary>
            public string AltText
            {
                get
                {
                    return this["AltText"] == null ? String.Empty : this["AltText"].Value<string>();
                }
            }
    
            /// <summary>
            /// Link To Document: A document to link to when the banner is clicked.
            /// </summary>
            public IPublishedContent LinkToPage
            {
                get
                {
                    return this["LinkToPage"] == null || String.IsNullOrEmpty(this["LinkToPage"].Value<string>()) ? null : UmbracoContext.Current.ContentCache.GetById(this["LinkToPage"].Value<int>());
                }
            }
    
            /// <summary>
            /// Link Query String: An optional query string to append to banner link.  Should start with a ? if used.
            /// </summary>
            public string LinkUrl
            {
                get
                {
                    return this["LinkUrl"] == null ? String.Empty : this["LinkUrl"].Value<string>();
                }
            }
    
            /// <summary>
            /// Hidden: If this item visible by default.  Items can be hidden and displayed through Test & Target.
            /// </summary>
            public bool Hidden
            {
                get
                {
                    return this["Hidden"] != null && this["Hidden"].Value<string>() == "1";
                }
            }
    
            /// <summary>
            /// Unique Name: Unique name for this item to use in analytics and scripting.
            /// </summary>
            public string UniqueName
            {
                get
                {
                    return this["UniqueName"] == null ? String.Empty : this["UniqueName"].Value<string>();
                }
            }
        }
    }
    
  • Chester Campbell 98 posts 209 karma points
    Jan 25, 2017 @ 22:45
    Chester Campbell
    0

    Building a property converter that modifies how Model Builder binds the property is certainly the best way to accomplish what you want to do.

    But for folks who don't want to go down that road I thought I'd share another option. Let the generated model properties remain IPublishedContent and IEnumerable<IPublishedContent> and instead use an HTML helper extension to map the IPublishedContent item to the generated model and then to a partial view.

    You can see the details in this gist: https://gist.github.com/ChesterCampbellAM/2e9e14de81a4ee242eee46ce6c4936e4

Please Sign in or register to post replies

Write your reply to:

Draft