In addition to what Mari said:
We tried to add BackingType with an implementation of the PropertyList<>. We can't see that it's triggering the ParseItem-code in our implementation (Like it does on the CMS).
What we are experiencing is that the serialized data we get in the Commerce-database (CatalogContentProperty) is not the same as we get when reading data through the contentRepository. The difference is on decimals, where we on the input have a precision of 5 decimals (which is also in the database) but when we retieve the data - we only have a precision of 0 decimal in the objects.
I might be out of date here (slightly), but the PropertyList should work fine as long as you specify the correct backing type. It'll be slightly revised in CMS 11, but I don't remember it being broken or not working ...
And yes we fully support PropertyList, so if anything is not working, let us know and we will look into it.
According to this: https://world.episerver.com/support/Bug-list/bug/COM-2394 PropertyList was supported as of Commerce 9.22.
But yes, we are experiencing some issues, see the comment from @Thomas above.
If you can provide more detail (test code to reproduce the problem), we will make sure to look into it
Hi Quan,
I used the Quicksilver-site to recreate the problem.
The model with a propertylist:
[CatalogContentType( GUID = "c1bc1c4e-4a46-4a03-8e90-71bec3576aff", MetaClassName = "FashionVariant", DisplayName = "Fashion Variant", Description = "Display fashion variant")] public class FashionVariant : VariationContent { [Searchable] [Tokenize] [IncludeInDefaultSearch] [BackingType(typeof(PropertyString))] [Display(Name = "Size", Order = 1)] public virtual string Size { get; set; } [Searchable] [CultureSpecific] [Tokenize] [IncludeInDefaultSearch] [BackingType(typeof(PropertyString))] [Display(Name = "Color", Order = 2)] public virtual string Color { get; set; } [BackingType(typeof(TestItemProperty))] public virtual IList<TestItem> TestItems { get; set; } } public class TestItem { public decimal DecimalValue { get; set; } } [PropertyDefinitionTypePlugIn] public class TestItemProperty : PropertyList<TestItem> { private Injected<ObjectSerializerFactory> _objectSerializerFactory; private IObjectSerializer _objectSerializer; public TestItemProperty() { _objectSerializer = this._objectSerializerFactory.Service.GetSerializer("application/json"); } public override PropertyData ParseToObject(string value) { ParseToSelf(value); return this; } protected override TestItem ParseItem(string value) { var testItem = _objectSerializer.Deserialize<TestItem>(value); return testItem; } }
The code the code that runs:
FashionVariant newVariant = _contentRepository.GetDefault<FashionVariant>(ContentReference.StartPage); newVariant.Name = "MyTest"; newVariant.Code = "MyTestCode"; newVariant.TestItems = new List<TestItem>(); newVariant.TestItems.Add(new TestItem()); newVariant.TestItems[0].DecimalValue = 1.0000000000m; var contentLink = _contentRepository.Save(newVariant, SaveAction.Publish, AccessLevel.NoAccess); var afterRead = _contentRepository.Get<FashionVariant>(contentLink); var string1 = newVariant.Property["TestItems"].ToRawString(); var string2 = afterRead.Property["TestItems"].ToRawString();
Result:
string1 = [{"decimalValue":1.0000000000}]
string2 = [{"decimalValue":1.0}]
So the precision level has changed. This causes problem for us when comparing objects.
In the CatalogContentProperty-table in the database, the value is stored like this:
[{"decimalValue":1.0000000000}]
I'm guessing here, but my gut says that this is likely a JsonSerializer problem than the PropertyList itself ...
The behavior should be the same for the type whether it's used on a cms content type or a catalog content type. Right now, they behave different (as described above). And also, BackingType is required for catalog content types.
Another thing, is that I did a little test:
I added this code to the TestItemProperty:
protected override TestItem ParseItem(string value) { var testItem = _objectSerializer.Deserialize<TestItem>(value); testItem.DecimalValue = 999999.999m; return testItem; }
I would expect the Deserializer to run, and always return 999999.999, but when I look at the objects, the value is still 1. So, is it using another mechanism here?
string2 = [{"decimalValue":1.0}]
So the precision level has changed. This causes problem for us when comparing objects.
In the CatalogContentProperty-table in the database, the value is stored like this:
[{"decimalValue":1.0000000000}]
=> This should be because of the Deserializer which does not respect the precision.
"I would expect the Deserializer to run, and always return 999999.999, but when I look at the objects, the value is still 1. So, is it using another mechanism here?"
=> Not sure I understand this. You set the value after the deserializer has run, right? Did you mean testItem still have value of 1.0?
1. Yes. The deserializer did not respect the precision.
2. Yes. I set the value after the deserializer, and the testItem still has value 1.0. Seems like it does not use the property in the backing type.
If I do the following with the JSON.net serializer:
TextReader textReader = new StringReader("[{\"decimalValue\":1.0000000000}]"); JsonReader reader = new JsonTextReader(textReader); var serializer = new Newtonsoft.Json.JsonSerializer(); var o = serializer.Deserialize(reader); TextWriter writer = new StringWriter(); serializer.Serialize(writer, o); string value = writer.ToString();
Value will be: [{\"decimalValue\":1.0}]
I have a gut feeling (without having tested it) that this happens when you deserialize the object without specifying the type. (I may be completely wrong here. :D)
I am interested to know if anyone has gotten this to work? The thread that is referenced in the bug isn't really clear on how exactly it was fixed. I have tried a few different backing types for my property to no avail. I was able to work around the issue by creating a block with my repeatable property and adding it as to a content reference on my variant. It works, but, it creates an extra layer that wouldn't be needed if the property could simply exist on the variant. It would be great if this could get fixed, or, if it is possible now, there was some solid documentation written on how to use it properly.
Like Mark I got it working with
[BackingType(typeof(TestItemProperty))]
We need to save store specfic data (80+ stores) on our product and variant items. The data needs to be queryable (through Find) and editable by commerce editors.
At the moment we are using PropertyList to store the data, but there seems to be some issues related to this, ref:
https://world.episerver.com/forum/developer-forum/-Episerver-75-CMS/Thread-Container/2016/2/propertylist-not-working---can-not-be-mapped-to-a-metadatatype/
Do you plan to fully support PropertyList type in Commerce? Any other suggestions on how to solve this?