U4-4575 - Checkboxlist DataType stores data differently on Content vs Members

Created by Chad T 01 Apr 2014, 05:09:30 Updated by Sebastiaan Janssen 03 Apr 2014, 07:33:33

I've created a new DataType based n the CheckboxList data type.

When I add this property to a regular 'Content' type, the data is returned as a string delimited array: "hello,world"

Am accessing this with: CurrentPage.GetPropertyValue("testprop");

When I do the exact same thing but with a Member, I get the ID's back instead: "1002,1007", etc. There doesn't seem to be a way to get the text values of the DataType?


Sebastiaan Janssen 01 Apr 2014, 16:49:20

@ChadT Can you please show us some code for the way you're getting the member and how you're then trying to get the property values? That way we can investigate better what might be going on.

Stephan 01 Apr 2014, 18:37:56

Discussing with Jeavon I think I have a potential cause. In both cases the IDs are stored in the database (ie "123,456"). But for content, we then generate the string value for the XML cache using the property editor ConvertDbToString method, which turns the IDs into prevalues (ie "blue,green"). Whereas for members we skip that step because there's not XML cache. This explains that.

Fix would consist in making sure that ConvertDbToString runs for members properties even though we don't have an XML cache. Need to look into it though.

Sebastiaan Janssen 01 Apr 2014, 19:24:50

@zpqrtbnk Well.. we used to have some kind of XML cache, at least this is what we used to teach on the courses:


            //Generate the member xml with .XmlGenerate
            member.XmlGenerate(new XmlDocument());

Not sure what it did though or if it's doing anything similar in the new member APIs.

Also beware of possible breaking changes of course, whatever happened in 7.0.4 should still do the same in 7.1.0 which is why I was asking for code from @ChadT to see how he was trying to get this property value.

Chad T 01 Apr 2014, 23:11:49

@sebastiaan I'm using code generated via the 'new template' dialogue.

var profileModel = Members.GetCurrentMemberProfileModel(); //seems to have been added in 7.1RC for (var i = 0; i < profileModel.MemberProperties.Count; i++) { profileModel.MemberProperties[i].Value; }

For what it's worth, I've tried to get the data a number of different ways. Umbraco.Member(123), Services.MemberServices.GetByXXX, which all return IMember and then accessing member.Properties[key];

All end up with the same result. I'm happy to try any other methods you're aware of. I've gone through all the different ways I can find of digging up member data and the result is always the same.

Stephan 02 Apr 2014, 07:16:19

@Sebastiaan: legacy member does generate XML though I have no idea what we do with it afterwards. But...

UmbracoHelper.TypedMember(id) ends up calling MemberService.GetById(id) to get a Member model, then wrap it in a MemberPublishedContent. Which creates properties as RawValueProperty instances, using member.Properties[alias].Value as source data. That is, using the thing that comes from the database.

In fact I just realized the current implementation of "NoCache" suffers the exact same issue. If we create IPublishedContent items entirely bypassing XML... we miss one transformation step.

I think we want to do something along

var peResolver = PropertyEditorResolver.Current; var dtService = ApplicationContext.Current.Services.DataTypeService; _properties = _publishedMemberType.PropertyTypes .Select(x => { var p = _member.Properties.SingleOrDefault( xx => xx.Alias == x.PropertyTypeAlias); var v = p == null || p.Value == null ? null : p.Value; if (v != null) { var e = peResolver.GetByAlias(x.PropertyEditorAlias); if (e != null) v = e.ValueEditor.ConvertDbToString(p, p.PropertyType, dtService); } return new RawValueProperty(x, v ?? string.Empty); }) .Cast() .ToArray();

In MemberPublishedContent ctor. Still need to understand the perfs impact. And might want Shannon to review this.

Stephan 02 Apr 2014, 07:48:17

(a) if we fix it here it would be a breaking change.

(b) I need to discuss it with Shannon. Any type of cache that is not working on top of the XML file is going to be impacted by the issue. Below is some notes so I remember what's going on...

In ''theory'' ConvertDbToString should ''not'' exist and conversions should take place in IPropertyValueConverter exclusively. But, coming from legacy, we have some value editors that store IDs in the DB and matching preValues in the XML. And so ConvertDbToString was invented as a workaround.

It was fine as long as XML was the only way to get the value. But with the new API, new caches... XML is just one way to get the value. Because it is the default one, IPropertyValueConverter has to assume that the raw data comes from XML ie has been through ConvertDbToString.

So whenever we create an IPublishedContent we have to figure out where the property values come from (raw DB or XML?) and apply ConvertDbToString where appropriate.

Things to keep in mind:

  • there's a ConvertDbToXml method that we need to take care of too.
  • what value goes in Examine? Ie when we re-create a Media from Examine... has ConvertDbToString been applied to property values already or not?
  • does this mean that IPropertyValueConverter will always receive a string, and never, say, an integer if there's an integer in the DB?

Stephan 02 Apr 2014, 09:45:31

More notes:

What goes to the XML is an XML fragment that comes out of ConvertDbToXml. At the moment most editors wrap the output of ConvertDbToString in a text node or a cdata node. In any case, ConvertDbToXml should return an XML version of ConvertDbToString // ConvertDbToString should return a string version of ConvertDbToXml. So all we have to take care of here is ConvertDbToString.

Tested Examine with CheckBoxList on content: the prevalues go into the index ie the index contains "blue,green" not "123,456" so no need to convert what we get from Examine. Still need to test for medias.

Stephan 02 Apr 2014, 09:46:16

Have pushed b6185b8 into 7.1.0 that should fix the members issue - anything else cannot change at that stage as 7.1.0 is frozen.

Sebastiaan Janssen 02 Apr 2014, 12:29:23

@zpqrtbnk I'm not sure this works as intended, the code @ChadT is using relies on our GetCurrentMemberProfileModel() method. Using that method I still get id's instead of strings.

Hmm, although, come to think of it, you'd want to edit and save this property's actual value, not the converted one. Never mind.

So in order to display values you can now use: var member = Members.GetByUsername(profileModel.UserName); var testpropValue = member.GetPropertyValue("testprop")

Sebastiaan Janssen 02 Apr 2014, 12:38:28

@zpqrtbnk One thing though, this also needs fixing for v6, but I have no PropertyEditorResolver there?

Stephan 02 Apr 2014, 13:21:17

About GetCurrentMemberProfileModel: I think this is meant to let ppl edit members on the front-end - so we want to work with actual property values, not converted values. So yes, the code you propose should work. About v6... looking into it. How we find out the property editors changes between 6 and 7.

Chad T 02 Apr 2014, 22:37:43

Hi guys, thanks for all your work on this. Confirming this will drop in 7.1 final?

Edit: Actually, thinking about this further - the feature I am currently building is to allow users to edit their own profile. and GetCurrentMemberProfile() seems to be the right way to dig up the data, but I also need to get a list of all the options for that given DataType (in my case, a CheckBoxList). This is perhaps a secondary case and not related, but unsure as to how I'd go about getting that data so I can display the entire list that a user can then check off.

Sebastiaan Janssen 03 Apr 2014, 07:33:33

@ChadT Make sure to head on over to the forums, I don't off the top of my head know either, but try finding how to get prevalues for a property editor / data type.

And yes, see the "Due in version" field. 6.2.0 and 7.1.0.

Priority: Normal

Type: Bug

State: Fixed


Difficulty: Normal


Backwards Compatible: True

Fix Submitted:

Affected versions: 7.1.0

Due in version: 7.1.0, 6.2.0


Story Points: