<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Blog posts by sunil</title><link href="http://world.optimizely.com" /><updated>2025-12-22T15:03:20.0000000Z</updated><id>https://world.optimizely.com/blogs/sunil/</id> <generator uri="http://world.optimizely.com" version="2.0">Optimizely World</generator> <entry><title>Handling Multiple Carts in a Single Sales Agent Session in Optimizely Commerce</title><link href="https://world.optimizely.com/blogs/sunil/dates/2025/12/handling-multiple-carts-in-a-single-sales-agent-session-in-optimizely-commerce/" /><id>&lt;p&gt;In assisted-commerce, call-center, and B2B scenarios, a &lt;strong&gt;Sales Agent&lt;/strong&gt; often needs to work on behalf of multiple customers within a single authenticated session.&lt;/p&gt;
&lt;p&gt;A typical requirement looks like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A Sales Agent logs in once (via OKTA)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Uses &lt;strong&gt;Select Customer&lt;/strong&gt; to choose a customer&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Manages a cart for that customer&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Switches to another customer&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Returns to the previous customer and continues where they left off.&lt;/p&gt;
&lt;p&gt;Out of the box, Optimizely Commerce assumes &lt;strong&gt;one active cart per user&lt;/strong&gt;, which makes this scenario non-trivial.&lt;/p&gt;
&lt;p&gt;This blog explains a &lt;strong&gt;clean, scalable pattern&lt;/strong&gt; for supporting &lt;strong&gt;multiple customer carts within a single Sales Agent session&lt;/strong&gt; in Optimizely Commerce 14.&lt;/p&gt;
&lt;h3&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;Challenges&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;By default, a cart in Optimizely Commerce is associated with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code style=&quot;display: inline;&quot;&gt;CustomerId&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Market&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cart name&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;In assisted-sales scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The &lt;strong&gt;logged-in user is the Sales Agent&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;strong&gt;actual shopper is the selected customer&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Sales Agent must manage &lt;strong&gt;multiple carts&lt;/strong&gt;, one per customer&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;&lt;strong&gt;Design Principle (which I used)&lt;/strong&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Treat the Sales Agent as an operator, not the cart owner.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Sales Agent identity remains constant&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Each customer has their &lt;strong&gt;own persisted cart&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Customer context switching is &lt;strong&gt;explicit&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Only one cart is active in the UI at a time&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/5b8a3667fea6429187b1692b3ff28568.aspx&quot; width=&quot;1352&quot; height=&quot;901&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So to achive this requirement I created a Endpoint which will accepts customer Id&#39;s for Active Customer &amp;amp; Selected Customer, so based on the customer Id&#39;s system will switch/choose the correct cart and make that cart as primary cart.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;Input Model for Customer Context Switching&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Customer switching is driven by a simple and explicit input model:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public class CustomerCartDetailsInputModel
{
    [DataMember(Name = &quot;activeCustomerId&quot;)]
    public string ActiveCustomerId { get; set; }

    [DataMember(Name = &quot;selectedCustomerId&quot;)]
    public string SelectedCustomerId { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Purpose:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code style=&quot;display: inline;&quot;&gt;ActiveCustomerId&lt;/code&gt; &amp;rarr; customer whose cart is currently active&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code style=&quot;display: inline;&quot;&gt;SelectedCustomerId&lt;/code&gt; &amp;rarr; customer chosen via &lt;strong&gt;Select Customer&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This avoids implicit session behavior and keeps cart ownership clear.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;Customer Cart Switching Endpoint&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Whenever a Sales Agent clicks &lt;strong&gt;Select Customer&lt;/strong&gt;, the frontend calls a single endpoint:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[HttpPost]
public async Task&amp;lt;JsonResult&amp;gt; Post(
    [FromBody] CustomerCartDetailsInputModel inputModel)
{
    return new JsonHttpStatusResult&amp;lt;CartGetViewModel&amp;gt;(
        await _customerCartService.UpdateCustomerCartAsync(inputModel),
        SerializerSettings.JsonDefault);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This endpoint acts as the &lt;strong&gt;single source of truth&lt;/strong&gt; for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Persisting the active customer&amp;rsquo;s cart&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Loading or creating the selected customer&amp;rsquo;s cart&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Switching the active cart context&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;High-Level Switching Flow&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Resolve Sales Agent identity&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Load or create the &lt;strong&gt;Sales Agent context cart&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Persist the active customer&amp;rsquo;s cart&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Load or create the selected customer&amp;rsquo;s cart&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Copy the selected customer cart into the Sales Agent context&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mark the selected customer as active&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;Simplified Cart Switching Logic (Core Pattern)&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Below is a cleaned-up version of the core logic, focused only on multi-cart handling:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public async Task&amp;lt;CartGetViewModel&amp;gt; UpdateCustomerCartAsync(
    CustomerCartDetailsInputModel inputModel)
{
    var salesAgentId = GetSalesAgentId();

    // Load or create Sales Agent context cart
    var agentCart = _orderRepository.LoadOrCreateCart&amp;lt;ICart&amp;gt;(
        salesAgentId, OrderNames.Default);

    // Ensure identifiers exist
    if (string.IsNullOrEmpty(inputModel.ActiveCustomerId))
        inputModel.ActiveCustomerId = Guid.NewGuid().ToString();

    if (string.IsNullOrEmpty(inputModel.SelectedCustomerId))
        inputModel.SelectedCustomerId = Guid.NewGuid().ToString();

    Guid.TryParse(inputModel.ActiveCustomerId, out var activeCustomerId);
    Guid.TryParse(inputModel.SelectedCustomerId, out var selectedCustomerId);

    // Persist active customer cart
    if (activeCustomerId != Guid.Empty)
    {
        var activeCustomerCart =
            _orderRepository.LoadCart&amp;lt;ICart&amp;gt;(activeCustomerId, OrderNames.Default)
            ?? _orderRepository.Create&amp;lt;ICart&amp;gt;(activeCustomerId, OrderNames.Default);

        activeCustomerCart.CopyFrom(agentCart, _orderGroupFactory);
        activeCustomerCart.CustomerId = activeCustomerId;

        _cartRepository.SaveCart(activeCustomerCart);
    }

    // Load or create selected customer cart
    var selectedCustomerCart =
        _orderRepository.LoadCart&amp;lt;ICart&amp;gt;(selectedCustomerId, OrderNames.Default)
        ?? _orderRepository.Create&amp;lt;ICart&amp;gt;(selectedCustomerId, OrderNames.Default);

    selectedCustomerCart.CustomerId = selectedCustomerId;

    // Switch active context
    agentCart.CopyFrom(selectedCustomerCart, _orderGroupFactory);
    agentCart.CustomerId = salesAgentId;

    _cartRepository.SaveCart(agentCart); // Save Cart

    return new CartGetViewModel
    {
        Cart = await BuildCartViewModel(agentCart), // Generate View Model of Cart
        CartCustomerId = selectedCustomerId.ToString()
    };
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;Understanding the &lt;code style=&quot;display: inline;&quot;&gt;CopyFrom&lt;/code&gt; Method&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code style=&quot;display: inline;&quot;&gt;CopyFrom&lt;/code&gt; is a core Optimizely Commerce API used to &lt;strong&gt;deep-copy an entire cart structure&lt;/strong&gt; from one order group to another.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;targetCart.CopyFrom(sourceCart, _orderGroupFactory);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;em&gt;What &lt;code style=&quot;display: inline;&quot;&gt;CopyFrom&lt;/code&gt; Does&lt;/em&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Copies line items, shipments, payments, and addresses&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Copies custom properties&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Recreates all entities using &lt;code style=&quot;display: inline;&quot;&gt;IOrderGroupFactory&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;&lt;em&gt;Why &lt;code style=&quot;display: inline;&quot;&gt;CopyFrom&lt;/code&gt; Is Essential Here&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;In multi-cart scenarios:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Customer carts must remain isolated&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Sales Agent context cart must fully switch state&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Partial updates are unsafe&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code style=&quot;display: inline;&quot;&gt;CopyFrom&lt;/code&gt; guarantees a &lt;strong&gt;clean cart switch without data leakage&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;By separating &lt;strong&gt;Sales Agent identity&lt;/strong&gt; from &lt;strong&gt;customer cart ownership&lt;/strong&gt; and using an explicit &lt;strong&gt;Select Customer&lt;/strong&gt; flow, you can build a scalable assisted-commerce experience on Optimizely Commerce&amp;nbsp; without fighting the platform.&lt;/p&gt;
&lt;p&gt;Below is the output of design:&lt;br /&gt;&lt;img src=&quot;/link/0f70c6f69b884ff8a771ae77652cc051.aspx&quot; /&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</id><updated>2025-12-22T15:03:20.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Implementing Custom Line Item Pricing in Optimizely Commerce 14</title><link href="https://world.optimizely.com/blogs/sunil/dates/2025/11/implementing-dynamic-pricing-in-optimizely-commerce/" /><id>&lt;p&gt;In many enterprise commerce implementations, business users often need the flexibility to override product pricing at the cart level - especially during customer service operations, B2B negotiations, or manual order creation.&lt;/p&gt;
&lt;p&gt;Recently, I had a client requirement where the &lt;strong&gt;Super Admin&lt;/strong&gt; (a special CMS/Commerce role) needed the ability to modify the &lt;strong&gt;price of each line item directly from the Cart page&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For Example:&lt;br /&gt;If the default price of a product is &lt;strong&gt;$1000&lt;/strong&gt;, a Super Admin should be able to change it to &lt;strong&gt;$900&lt;/strong&gt;, &lt;strong&gt;$850&lt;/strong&gt;, or any custom value - &lt;em&gt;even if this price is not defined in the price lists&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This custom pricing must also continue to work correctly with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The promotions engine&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Tax calculations&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Recalculation workflows&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Order totals&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To meet this requirement cleanly and safely, we needed a way to override &lt;strong&gt;PlacedPrice&lt;/strong&gt; at the line item level in a way that stays aligned with Commerce&amp;rsquo;s pricing pipeline.&lt;/p&gt;
&lt;p&gt;This blog explains &lt;strong&gt;the correct, Commerce-native way&lt;/strong&gt; to implement custom line-item pricing.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Use a Custom Price Processor&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;To implement custom pricing properly, we must plug into Commerce&amp;rsquo;s pricing pipeline via &lt;code style=&quot;display: inline;&quot;&gt;IPlacedPriceProcessor&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1 - Store the Custom Price on the Line Item&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When a Super Admin updates the price on the cart page:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;lineItem.Properties[&quot;SuperAdminCustomPrice&quot;] = customPrice.ToString(); // SuperAdminCustomPrice is meta field
_cartRepository.SaveCart(cart);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This property persists with the cart/item.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2 - Implement the Custom Price Processor&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[ServiceConfiguration(typeof(IPlacedPriceProcessor))]
public class SuperAdminPriceProcessor : DefaultPlacedPriceProcessor
{
    public override void ApplyPlacedPrice(
        IOrderGroup orderGroup,
        IOrderForm orderForm,
        ILineItem lineItem,
        IMarket market)
    {
        // Allow Commerce to set its default price
        base.ApplyPlacedPrice(orderGroup, orderForm, lineItem, market);

        // Check for Super Admin&amp;rsquo;s custom price
        if (!lineItem.Properties.ContainsKey(&quot;SuperAdminCustomPrice&quot;))
        {
            return;
        }

        if (decimal.TryParse(
            lineItem.Properties[&quot;SuperAdminCustomPrice&quot;].ToString(),
            out var customPrice))
        {
            // Save original Commerce price for audit/rollback
            lineItem.Properties[&quot;OriginalPlacedPrice&quot;] = lineItem.PlacedPrice;

            // Apply custom override
            lineItem.PlacedPrice = customPrice;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3 - How It Looks in the UI&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Your &amp;ldquo;Edit Price&amp;rdquo; option on the cart page simply updates the custom property:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;if (User.IsInRole(&quot;SuperAdmin&quot;))
{
    lineItem.Properties[&quot;SuperAdminCustomPrice&quot;] = newPrice;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This was exactly what the client needed:&lt;br /&gt;A clean, production-safe way for &lt;strong&gt;Super Admins to override line item prices&lt;/strong&gt; without breaking any Commerce functionality.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Thanks,&lt;/p&gt;
&lt;p&gt;Sunil Kumar&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</id><updated>2025-11-28T15:08:51.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Delete Multiple Variants From Product &amp; Catalog</title><link href="https://world.optimizely.com/blogs/sunil/dates/2021/2/delete-all-variants-from-catalog/" /><id>&lt;p&gt;In EpiServer sometimes you need to &lt;strong&gt;Delete &lt;/strong&gt;Multiple Variants from a &lt;strong&gt;Catalog&lt;/strong&gt; and &lt;strong&gt;Product&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;We can do that by using &lt;strong&gt;CatalogSystem.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here I am going to show you how we can remove the Variants from Product &amp;amp; Catalog.&lt;/p&gt;
&lt;p&gt;We may have two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Delete Variants by Product&lt;/li&gt;
&lt;li&gt;Delete all Variants under Catalog&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To perform this we will pull all the catalog items first then we will look product nodes under it then variants and remove those.&lt;/p&gt;

&lt;p&gt;Delete Variants by Products:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public void DeleteVariantsByProduct(ContentReference productContentReference)
        {
            var children = _contentRepository.GetChildren&amp;lt;CatalogContentBase&amp;gt;(productContentReference);

            foreach (var child in children)
            {
                if (child.GetType().BaseType == typeof(VariationContent))
                {
                    try
                    {
                        // Delete 
                        _catalogSystem.DeleteCatalogEntry(child.ContentLink.ID, true);
                    }
                    catch (Exception exception)
                    {
                        // Log Exception
                    }
                }
            }
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I created a Variant Service Class where you can find the two Methods for &lt;strong&gt;Delete Variants by Product&lt;/strong&gt; and &lt;strong&gt;Delete all Variants under Catalog&lt;/strong&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;using EPiServer;
using EPiServer.Commerce.Catalog.ContentTypes;
using EPiServer.Core;
using Mediachase.Commerce.Catalog;
using System;

namespace DemoCommerce
{
    public class VariantService
    {
        private readonly ICatalogSystem _catalogSystem;
        private readonly IContentRepository _contentRepository;
        private readonly ReferenceConverter _referenceConverter;

        public VariantService(
            ICatalogSystem catalogSystem,
            IContentRepository contentRepository,
            ReferenceConverter referenceConverter)
        {
            _catalogSystem = catalogSystem ?? throw new ArgumentNullException(nameof(catalogSystem));
            _contentRepository = contentRepository ?? throw new ArgumentNullException(nameof(contentRepository));
            _referenceConverter = referenceConverter ?? throw new ArgumentNullException(nameof(referenceConverter));
        }

        public void DeleteVariantsByProduct(ContentReference productContentReference)
        {
            var children = _contentRepository.GetChildren&amp;lt;CatalogContentBase&amp;gt;(productContentReference);

            foreach (var child in children)
            {
                if (child.GetType().BaseType == typeof(VariationContent))
                {
                    try
                    {
                        // Delete 
                        _catalogSystem.DeleteCatalogEntry(child.ContentLink.ID, true);
                    }
                    catch (Exception exception)
                    {
                        // Log Exception
                    }
                }
            }
        }

        public void DeleteAllVariants()
        {
            // Get Catalog Node Items
            var catalogItems = _contentRepository.GetChildren&amp;lt;CatalogContent&amp;gt;(_referenceConverter.GetRootLink());

            foreach (var catalogItem in catalogItems)
            {
                //Loop through all catalog items
                var nodes = _contentRepository.GetChildren&amp;lt;CatalogContentBase&amp;gt;(catalogItem.ContentLink);

                foreach (var node in nodes)
                {
                    DeleteCatalogEntries(node);
                }
            }
        }

        private void DeleteCatalogEntries(CatalogContentBase node)
        {
            var children = _contentRepository.GetChildren&amp;lt;CatalogContentBase&amp;gt;(node.ContentLink);

            foreach (var child in children)
            {
                switch (child.ContentType)
                {
                    case CatalogContentType.CatalogNode:
                        DeleteCatalogEntries(child);
                        break;
                    case CatalogContentType.CatalogEntry:
                        if (child.GetType().BaseType == typeof(VariationContent))
                        {
                            try
                            {
                                // Delete 
                                _catalogSystem.DeleteCatalogEntry(child.ContentLink.ID, true);
                            }
                            catch (Exception exception)
                            {
                                // Log Exception
                            }
                        }

                        break;
                }
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Thanks &amp;amp; Regards&lt;/p&gt;
&lt;p&gt;Sunil&lt;/p&gt;</id><updated>2021-02-28T16:57:08.0000000Z</updated><summary type="html">Blog post</summary></entry></feed>