Hide menu Last updated: Oct 12 2015

This topic describes how to work with bundles and packages in relation to the content model.

How it works

The Target property of the BundleEntry or PackageEntry contains the ContentReference of the entry included in the bundle/package. The class also has a SortOrder property for ordering the entries, a GroupName property for grouping entries, and a Quantity property containing the quantity of the entry in the bundle/package.

EPiServer.Commerce.Catalog.Linking.EntryRelation contains the following default values: DefaultGroupName and DefaultQuantity.

A BundleEntry or PackageEntry is uniquely defined by the ContentReference in its Target property together with its Source property (referencing the bundle or package itself); that is, you cannot add the same entry more than once to the same bundle or package. Use the Quantity property to set the quantity of an entry in a bundle or package.

Getting the entries of a bundle/package

By calling the GetRelationsBySource method of ILinksRepository with the ContentReference of a bundle/package, and filtering for either BundleEntry or PackageEntry, you get the bundle/package entries:

C#
public IEnumerable<BundleEntry> ListBundleEntries(ContentReference referenceToBundle)
{
    var linksRepository = ServiceLocator.Current.GetInstance<ILinksRepository>();
    var allRelations = linksRepository.GetRelationsBySource(referenceToBundle);

    // Relations to bundle entries are of type BundleEntry
    var variations = allRelations.OfType<BundleEntry>().ToList();
    return variations;
}

Getting the bundle/package by an entry

By calling the GetRelationsByTarget method of ILinksRepository with the ContentReference of a catalog entry, and filtering for PackageEntry or BundleEntry, you get the packages/bundles:

C#
public IEnumerable<BundleEntry> GetBundleByEntry(ContentReference entry)
{
    var linksRepository = ServiceLocator.Current.GetInstance<ILinksRepository>();
    var allRelations = linksRepository.GetRelationsByTarget(entry);

    // Relations to Product is ProductVariation
    return allRelations.OfType<BundleEntry>().ToList();
}
Adding an entry to a bundle/package

The UpdateRelations method or UpdateRelation extension method of ILinksRepository can be used to add new BundleEntry or PackageEntry objects to a bundle or package. The new entry must have a Target ContentReference, a Source ContentReference, and you probably want to specify a Quantity and Group.

C#
public void AddBundleEntry(ContentReference referenceToBundle, ContentReference referenceToProductOrVariation)
{
    var linksRepository = ServiceLocator.Current.GetInstance<ILinksRepository>();

    var newBundleEntry = new BundleEntry
    {
        GroupName = "GroupX",
        Quantity = 1.0m,
        SortOrder = 100,
        Source = referenceToBundle,
        Target = referenceToProductOrVariation
    };

    linksRepository.UpdateRelation(newBundleEntry);
}

Updating an entry in a bundle/package

You also can use the UpdateRelations method or UpdateRelation extension method of ILinksRepository to update BundleEntry or PackageEntry objects, such as updating the Quantity. You can construct a new object to replace the old one (matched by the Source and Target properties), or use GetRelationsBySource to get the existing Relations, filter out the object you want to update, and pass it to UpdateRelation after changing the value.

C#
public void UpdateBundleEntry(ContentReference referenceToBundle, ContentReference referenceToProductOrVariation, decimal newQuantity)
{
    var linksRepository = ServiceLocator.Current.GetInstance<ILinksRepository>();
    var allRelations = linksRepository.GetRelationsBySource(referenceToBundle);

    // Find the matching BundleEntry by comparing the target, ignoring versions since relations are not version specific
    var matchingEntry =
        allRelations.OfType<BundleEntry>()
                    .FirstOrDefault(r => r.Target.CompareToIgnoreWorkID(referenceToProductOrVariation));

    // Update if there was a matching entry
    if (matchingEntry != null)
    {
        // Set new data
        matchingEntry.Quantity = newQuantity;

        linksRepository.UpdateRelation(matchingEntry);
    }
}

Removing an entry from a bundle/package

By calling the RemoveRelations method or RemoveRelation extension method of ILinksRepository with a BundleEntry or PackageEntry object matching an existing bundle/package entry, that entry is removed from the bundle/package. You can construct a matching object, or use GetRelationsBySource to get the existing Relations, filter out the object you want to remove, and pass it to RemoveRelation.

C#
public void RemoveBundleEntry(ContentReference referenceToBundle, ContentReference referenceToProductOrVariation)
{
    var linksRepository = ServiceLocator.Current.GetInstance<ILinksRepository>();

    // Define a relation matching the one to remove, or use
    // GetRelations to find the one you want to remove and pass that to
    // RemoveRelation
    var relationToRemove = new BundleEntry
    {
        // Source is required here to match the correct relation
        Source = referenceToBundle,
        Target = referenceToProductOrVariation
    };

    // Removes matching BundleEntry, or no action if no match exists
    linksRepository.RemoveRelation(relationToRemove);
}

Comments