Posted on 20/10/2025 12:39:23
Hi Mario
InolexProductViewModel’s constructor runs before the Id, VariantId, and LanguageId are populated — so calling
Services.Products.GetProductById(Id, VariantId, LanguageId) inside the constructor won’t work because those values are still null at that stage.
More importantly, you should be very careful to hold or lazily create a Product instance inside a view model.
A ProductViewModel belongs purely to the presentation layer — it’s meant for rendering, binding, or serialization.
If you start pulling in domain objects (like Product) from there, you break separation of concerns and create several serious risks:
-
Hidden database calls during rendering or serialization.
-
Massive circular object graphs if ever serialized to JSON.
-
Hard-to-track performance bottlenecks and caching issues.
Instead of putting that logic inside the view model, use a pattern where the domain object is explicitly fetched when needed.
In general you should avoid doing properties on viewmodels except for very specific situations where you need the property serialized in e.g. the /dwapi. In any other situation you should use an extension method instead.
You can do something like this:
public class InolexProductViewModel : Dynamicweb.Ecommerce.ProductCatalog.ProductViewModel
{
private Lazy<Product?>? _productLazy;
private Lazy<Product?> ProductLazy =>
_productLazy ??= new Lazy<Product?>(() =>
{
if (string.IsNullOrEmpty(Id))
return null;
return Products.GetProductById(Id, VariantId, LanguageId);
});
public Product? GetProduct() => ProductLazy.Value;
public decimal? GetWeightedPrice()
{
var product = GetProduct();
if (product == null)
return null;
var weight = product.Weight > 0 ? product.Weight : 1;
var price = product.Price.Price ?? 0;
return price * (decimal)weight;
}
public IList<Entities.ProductPrice> GetPricesWithWeight()
{
var product = GetProduct();
if (product == null)
return Array.Empty<Entities.ProductPrice>();
return new List<Entities.ProductPrice>
{
new Entities.ProductPrice { Weight = product.Weight, Value = product.Price.Price ?? 0 }
};
}
}