Copied to clipboard

Flag this post as spam?

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


  • Simone Chiaretta 134 posts 541 karma points c-trib
    Mar 02, 2016 @ 09:50
    Simone Chiaretta
    0

    If I convert from custom json, should source and object have the same value in a property value converter?

    I'm building my first property value converter for a custom data type that stores the model in JSON format and even after reading the very good documentation I still cannot understand when Source and Object are used and why Source matters.

    I understood that Object is what is returned by GetPropertyValue and in my case it should return the deserialized JSON object into a .NET class, but what should the Source be? The native representation of my JSON object is either the string (in that case is would be the same as Data) or the deserialized JSON (in which case is would be the same as Object).

    Can someone help clear this for me? Thx

  • Jeroen Breuer 4908 posts 12265 karma points MVP 4x admin c-trib
    Mar 02, 2016 @ 12:37
    Jeroen Breuer
    0

    Hello,

    I've created some simple property value converters. I always only use ConvertSourceToObject and never had any issues. For example: https://github.com/jbreuer/Hybrid-Framework-for-Umbraco-v7-Best-Practises/blob/master/Umbraco.Extensions/PropertyConverters/ImageCropperConverter.cs

    Jeroen

  • Simone Chiaretta 134 posts 541 karma points c-trib
    Mar 02, 2016 @ 13:19
    Simone Chiaretta
    0

    In this last few hours I've done a bit of searching and best option is to extend PropertyValueConverterBase and implement the ConvertDataToSource method only.

    It is then PropertyValueConverterBase that copies Source to Object

  • Stephen 767 posts 2273 karma points c-trib
    Mar 02, 2016 @ 14:57
    Stephen
    104

    Why 'Source' and 'Object'

    The original requirement driving it all is this: we want to limit the number of conversions, so that if, in the same view, you invoke Model.GetPropertyValue("foo") twice we run the converter only once. Meaning that, with strongly typed models, you can render @Model.Foo as many times as you want without thinking about performance issues.

    This means that we have to cache the results of the conversions, somehow. With the current XML cache, it is easy: we just store the value in the IPublishedContent object, since the cache re-creates these objects for each request anyways.

    It is not perfect, though: if a conversion is expensive, and is repeated on every page, ie on every request... this has a cost.

    To improve that situation, new versions of the cache (such as NuCache) propose to cache IPublishedContent objects and the converted values accross requests. Ie, there would only be one instance of the content object for content node 1234, shared by all views. And conversion would therefore run only once.

    The issue, then, is cache refresh. If conversion is purely local to the content, for example converting a string into a DateTime, then the result of the conversion is valid until the content itself is replaced.

    However, if the result of the conversion depends on other content items, eg in the case of a content picker, this is not true anymore. The result of the conversion becomes invalid as soon as any other content changes.

    With that in mind, we (I) devised the following mechanism: conversion is a two-step operation, going from 'Raw' to 'Source' and then from 'Source' to 'Object', and 'Source' and 'Object' can be cached at different levels.

    The basic example would be: 'Raw' is a string containing the ID of a node, 'Source' is the corresponding integer and can be cached for as long as the content does not change, 'Object' is the target content object and can be cached for as long as no other content changes.

    Each converter can declare at which level its 'Source' and 'Object' values should be cached.

    What should I implement?

    Considering that projects, today, run on the XML cache, the two-steps thing can be safely ignored. Which means that you should decide to implement either 'Raw' to 'Source' or 'Source' to 'Object' and be done with it. As Jeroen says... implement ConvertSourceToObject and be happy.

    What about the future?

    Practically, no project has ever used the two-steps system, except for my own experiments. And it tends to be cumbersome or not bring the expected improvements. To make it short, it's probably too complex to have variable cache levels per converter.

    As we slowly look into merging NuCache into v8, I am looking into refactoring that part. Not sure how to do it and gladly accepting ideas. Latest was: have 'Source' cached at content level (ie cached for as long as the 'Raw' value does not change) and 'Object' not cached at all.

    Making sense?

  • Simone Chiaretta 134 posts 541 karma points c-trib
    Mar 02, 2016 @ 15:08
    Simone Chiaretta
    0

    Thanks for the detailed explanation of the whole system.

    So, for now, I'll just implement ConvertSourceToObject where source is basically the raw data stored in the property, and in the future we'll see :)

  • Jeroen Breuer 4908 posts 12265 karma points MVP 4x admin c-trib
    Mar 02, 2016 @ 16:31
    Jeroen Breuer
    1

    You can experiment with NuCache ("Le Cache Nouveau") already. The source code is available here: https://github.com/umbraco/Umbraco-CMS/tree/dev-v7-contentcache

    In this video I explain how I've upgraded a project to NuCache: https://youtu.be/DWjbJiIUQdk?t=31m8s

    It can be downloaded here: https://github.com/jbreuer/1-1-multilingual-example/tree/NuCache

    Jeroen

  • Jeroen Breuer 4908 posts 12265 karma points MVP 4x admin c-trib
    Mar 19, 2016 @ 04:05
    Jeroen Breuer
    0

    Today I've been doing some more experiments with NuCache. I've been having some issues with MultipleTextStringValueConverter and RteMacroRenderingValueConverter.

    If you look at the source code you can see that these do some very different things in ConvertDataToSource and ConvertSourceToObject

    https://github.com/umbraco/Umbraco-CMS/blob/d50e49ad37fd5ca7bad2fd6e8fc994f3408ae70c/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs#L64

    https://github.com/umbraco/Umbraco-CMS/blob/d50e49ad37fd5ca7bad2fd6e8fc994f3408ae70c/src/Umbraco.Core/PropertyEditors/ValueConverters/TinyMceValueConverter.cs#L20

    In the NuCache version the following doesn't work for RTE properties:

    this.GetPropertyValue<IHtmlString>("alias")
    

    The following does work:

    new MvcHtmlString(this.GetProperty("alias").Value.ToString())
    

    In MultipleTextStringValueConverter even only ConvertDataToSource is implemented.

    https://github.com/umbraco/Umbraco-CMS/blob/d50e49ad37fd5ca7bad2fd6e8fc994f3408ae70c/src/Umbraco.Core/PropertyEditors/ValueConverters/MultipleTextStringValueConverter.cs#L20

    So if NuCache will start using ConvertDataToSource some pieces probably need to be updated because even the core value converters aren't consistent.

    Jeroen

  • Stephen 767 posts 2273 karma points c-trib
    Mar 21, 2016 @ 08:52
    Stephen
    0

    Few things.

    NuCache at the moment uses both ConvertDataToSource, and ConvertSourceToObject, and can handle different levels of cache for Source and Object. That was the whole point of having Source and Object, different levels of cache.

    Now, in theory, if eg ConvertDataToSource is not implemented, then Source is assumed to be identical to Data, and that is it. Similarly, if ConvertSourceToObject is not implemented, Object is assumed to be identical to Source.

    The important difference between NuCache and XmlCache is that NuCache as one and only one copy of a given IPublishedContent which is then shared by all requests. Meaning that anything that is not cached at request level is cached for a loooong time, whereas in XmlCache it is re-calculated on each request. This is where ppl may see differences.

    And this is why we have this Data-to-Source then Source-to-Object thing. Source could be cached at content level (eg parsing a JSON string into a JSON structure) and Object at request level (eg the IPublishedContent object corresponding to an ID).

    However, I am not entirely convinced that this system is that efficient. And, the good thing with having clean code, it should be quite easy to amend. I'm open to discussions!

Please Sign in or register to post replies

Write your reply to:

Draft