Copied to clipboard

Flag this post as spam?

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


  • Mikael Axel Kleinwort 154 posts 499 karma points c-trib
    Jan 25, 2020 @ 14:19
    Mikael Axel Kleinwort
    0

    How to access dictionary inside of an “object” type returned by ContentPropertyDisplay.Config["items"]

    This is probably not an Umbraco but a basic C# issue, however I give the entire context to make it easier to reproduce.

    I try to get the list of defined prevalues of a radio button list property editor in C# in server code, not client-side. This is in order to set a default value for the options list when the property is edited by content editors.

    Setting the default value in itself works. Now I want to read the defined prevalues, in order to select the first one (in sort order) as default.

    I successfully managed to plug into the EditorModelEventManager.SendingContentModel event following this guide.

    After retrieving the ContentPropertyDisplay instance like this:

    var propertyDisplay = e.Model
        .Variants.FirstOrDefault()
        .SelectMany(v => v.Tabs)
        .SelectMany(t => t.Properties)
        .Where(p => p.Alias == "myPropertyAlias")
        .FirstOrDefault()
    

    it has the Config property which is of type IDictionary<string, object> and within Config["items"], I can access an Object containing the prevalue items.

    var configItemsElement = propertyDisplay.Config["items"]
    

    Typing configItemsElement in VisualStudio's Immediate window outputs:

    Count = 3
        [0]: {[1, {{ value = SeoChoiceInherit, sortOrder = 1 }}]}
        [1]: {[2, {{ value = SeoChoiceYes, sortOrder = 2 }}]}
        [2]: {[3, {{ value = SeoChoiceNo, sortOrder = 3 }}]}
    

    so I can see the 3 prevalues I have defined in the BackOffice for the property.

    Typing configItemsElement.ToString() gives this type information:

    System.Collections.Generic.Dictionary`2[System.String,<>f__AnonymousType7`2[System.String,System.Int32]]
    

    This is as far as I get. I cannot access the prevalues stored in configItemsElement. For instance

    configItemsElement[1]
    

    results in error CS0021: Cannot apply indexing with [] to an expression of type 'object'

    In VisualStudio's "Autos" window, the information for configItemsElement is

    configItemsElement
    Value: Count = 3
    Type: object {System.Collections.Generic.Dictionary<string, <>f__AnonymousType7<string, int>>}
    

    What does this type information mean? How can I cast this object to a type I can use? Any cast I try results in errors.

  • Mikael Axel Kleinwort 154 posts 499 karma points c-trib
    Jan 26, 2020 @ 23:34
    Mikael Axel Kleinwort
    100

    The problem is caused by the ContentPropertyDisplay.Config["items"]collection using an anonymous type for its items. This leakage of anonymous type makes a regular cast from object to Dictionary or List impossible.

    I found a working solution with reflection. The way I finally got it to work is to:

    • declare my own type for the anonymous type
    • cast configItemsElement to IEnumerable
    • iterate over the dictionary inside of configItemsElement
    • get the 'inner item' of each dictionary item using reflection
    • cast the 'inner item' (of anonymous type) to dynamic
    • and use reflection to access the 2 properties of the 'inner item' (value and sortOrder) to add them to a new list

    This is my working code:

    ...
    
    public class InnerItemType
    {
        public int sortOrder { get; set;  }
        public string value { get; set; }
    }
    
    ....
    
    List<InnerItemType> listOptions = new List<InnerItemType>();
    
    var configItemsElement = propertyDisplay.Config["items"] as IEnumerable;
    
    foreach (var item in configItemsElement)
    {
        dynamic innerItem = item.GetType().GetProperties()[1].GetValue(item);
        listOptions.Add(new InnerItemType() { 
            value = innerItem.GetType().GetProperties()[0].GetValue(innerItem), 
            sortOrder = innerItem.GetType().GetProperties()[1].GetValue(innerItem)
        });
    }
    ...
    

    See this StackOverflow issue for more details. See this issue report on GitHub.

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies