Storing custom class instances on VariationContent.

Vote:
 

(This might belong in the Commerce forum, was unsure where to put it.) I'm fairly new to episerver, so sorry if I'm asking stupid questions.

We are moving our ProductImages out of Epi, and handeling them in a external service, that will provide epi with only a (string)path and a (string)type. I'm making a scheduled job to iterate over our products, and for each product iterate over our variants to find all the images for that variant and store them on the variant.

But I'm unsure about how to best store this data on the variant. Each variant needs to store a property for the main packshot, a property for the main modelshot, and a collection of the remaining images. 

One could say that i should store them in the folderstructure as extentions of the ImageData or MediaData classes. But we do not need nor wan't to have this in the allready bloated folderstructure, as it would never be managed in the editor, everything would be managed programaticly. So I'm hoping that the answer is not that this is how you should do this. 

The solution i have been trying to implement, storing the data in a class that extends the block class:

public class ProductImageBlock : BlockData
{
    public virtual string Type { get; set; }
    public virtual string Path { get; set; }
}

These are added to the BaseVariant class like this: 

public class BaseVariant : VariationContent
{
   ...
   public virtual ProductImageBlock PackshotMain { get; set; }
   public virtual ProductImageBlock ModelshotMain { get; set; }
   public virtual IList<ProductImageBlock> Images { get; set; }
}

And in the scheduled job i do the following: 

var wcVariant = variant.CreateWritableClone<BaseVariant>();
var changed = false;

if (mainPackshot != null && mainPackshot != wcVariant.PackshotMain)
{
    changed = true;
    wcVariant.PackshotMain = mainPackshot;
}

if (mainModelshot != null && mainModelshot != wcVariant.ModelshotMain)
{
    changed = true;
    wcVariant.ModelshotMain = mainModelshot;
}

if (images != null && images.Count > 0 && images.Equals(wcVariant.Images))
{
    changed = true;
    wcVariant.Images = images;
}

if (!changed)
    continue;

var contentRefrence = _contentRepository.Save(wcVariant, SaveAction.Publish | SaveAction.SkipValidation, AccessLevel.NoAccess);

Inspecting wcVariant in debug, i can see the blocks with data on it. But if i load the variant from the contentRefrence after the save, there is a block on variant, but the fields of the block are both null.

Am i doing something oviously wrong in my attempt above, or can it be fixed with a slight adjustment?
Or is there a better aproch to this, that i should implement instead?

Thanks in advance for any answers. 

#265125
Oct 15, 2021 8:30
Vote:
 

Binary data MUST be stored in the assets area as the content in here goes to wherever you've configured your data sotre (local file storage or in Azure a Blob provider).

The correct way is to upload binary data such as images in to the asset area then link to it with a ContentReference on the Variant. 

#265131
Oct 15, 2021 10:54
Vote:
 

But I'm not storing any binary data, only a image url as a string, and a image type as a string? The images themselves are not handled by epi at all, we have an external service that manages the images, and provides the CDN path to EPI. 

#265132
Oct 15, 2021 10:58
Vote:
 

You probably want to do this

wcVariant.PackshotMain.Type = ...;

wcVariant.PackshotMain.Path = ...;

The approach is fine, I am just not sure if you need to use BlockData for this. Simple, flat properties might be better and easier 

#265135
Oct 15, 2021 13:09
Vote:
 

Apologies I was skim reading as I was going in to a meeting. I agree with Quan there can be issues with using Blocks as properties when you're changing structure of model so I try to avoid.

I would also try to use https://world.optimizely.com/documentation/developer-guides/CMS/Content/Properties/generic-propertylist/ instead of a list of blocks if you're not using the blocks for rendering, it makes the editing a lot easier and blocks are designed to be rendered components (when not using as a property which as said I personally avoid).

#265137
Oct 15, 2021 13:31
Vote:
 

Thanks for your answers.

I fully agree that using blocks as properties, is not the ideal way to go.

public class ProductImageModel
{
    public virtual string Type { get; set; }
    public virtual string Path { get; set; }
}

But when i try to assign the above model to the variant, i get: "System.NotSupportedException: The type *********.ProductImageModel can not be mapped to a MetaDataType".

Any ideas on how to solve that?

I have a thought that adding a backingtype of some sort might do the trick, but I have'nt figured out a configuration that works yet.

#265260
Oct 18, 2021 12:44
Vote:
 

THe content system does not understand ProductImageModel and how it should be handled. You will need to define a PropertyData that can handle that, then using something like

        [BackingType(typeof(PropertyProductImage))]
        public virtual PropertyProductImage Image{ get; set; }

#265264
Oct 18, 2021 13:20
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.