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 140 posts 484 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 140 posts 484 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.

Please Sign in or register to post replies

Write your reply to:

Draft