ICartOrderProvider
This provider is used in several places on the Storefront, including on the Cart page and during the checkout process.
Methods
CustomerOrder GetCartOrder();
Retrieves the cart for the current user.
CustomerOrder GetOrCreateCartOrder();
Retrieves the cart for the current session. If a cart does not exist for the current session, a cart will be created and associated with the session.
void SetCartOrder(CustomerOrder customerOrder);
Associates the cart (customer order) with the current session. This method is called by the GetOrCreateCartOrder if and after a cart is created.
- customerOrder – The cart to associate with the current session.
void ClearCache();
If the cart provider stores the current cart in a cache (like using the PerRequestCacheManager), this will clear the current cart from that cache.
Remarks
Configured Commerce provides three standard implementations: CartOrderProviderByCustomer, CartOrderProviderByShipTo, and CartOrderProviderByUser. The CartOrderProviderByCustomer associates a cart with the user that created the cart (added products) and the Bill To customer being used at the time the cart was created. The CartOrderProviderByShipTo associates a cart with the user that created the cart and the Ship To customer being used at the time the cart was created. The CartOrderProviderByUserassociates a cart with the user that created the cart. Depending on the implementation being used, the current session could include the user who created the cart or the bill-to or ship-to customer being used when the cart was created. Usually these customers are selected immediately after logging into the Storefront.
Only one provider is used at a time. The cart order provider can be configured in the Admin Console using the Site Configurations > Providers > Cart Provider setting.

Implementations of the ICartOrderProvider must be decorated with the ependencyName] attribute. The DependencyName attribute takes a name as an argument. The name will be used to register the implementation in the IOC container. In the Admin Console, the name will appear in the dropdown when selecting a cart provider. This is how the application will know which cart provider to use during runtime.
Example: Associate the cart with the current user
ependencyName("ByUser")]
public class CartOrderProviderByUser : ICartOrderProvider
{
private int? cartRetentionDays;
/// <summary>The customer order key.</summary>
protected const string CustomerOrderKey = "CurrentCustomerOrder";
/// <summary>The cookie manager.</summary>
protected readonly ICookieManager CookieManager;
/// <summary>The customer order utilities.</summary>
protected readonly ICustomerOrderUtilities CustomerOrderUtilities;
/// <summary>The per request cache manager.</summary>
protected readonly IPerRequestCacheManager PerRequestCacheManager;
/// <summary>The unit of work.</summary>
protected readonly IUnitOfWork UnitOfWork;
/// <summary>The cart settings.</summary>
protected readonly CartSettings CartSettings;
/// <summary>Gets the cart cookie name.</summary>
protected virtual string CartCookieName => SiteContext.Current.WebsiteDto.Id + "_Cart";
/// <summary>Number of days to retain shopping cart.</summary>
protected virtual int CartRetentionDays => this.cartRetentionDays ?? (this.cartRetentionDays = this.CartSettings.RetentionDays).Value;
/// <summary>Keep cart from browser session after login.</summary>
protected virtual bool KeepCartAfterLogin => true;
/// <summary>Base filter for getting customer order.</summary>
protected virtual IQueryable<CustomerOrder> ApplyCustomerOrderBaseFilter(IQueryable<CustomerOrder> query)
{
var minValidOrderDate = this.CartRetentionDays > 0
? DateTimeProvider.Current.Now.AddDays(-this.CartRetentionDays)
: DateTimeOffset.MinValue;
var currentUserProfile = SiteContext.Current.UserProfile ?? SiteContext.Current.RememberedUserProfile;
return query.Where(co => co.WebsiteId == SiteContext.Current.WebsiteDto.Id
&& co.InitiatedByUserProfileId == currentUserProfile.Id
&& (co.Status == CustomerOrder.StatusType.Cart || co.Status == CustomerOrder.StatusType.PunchOut)
&& co.OrderDate > minValidOrderDate);
}
/// <summary>Additional filter for getting customer order.</summary>
protected virtual IQueryable<CustomerOrder> ApplyCustomerOrderAdditionalFilter(IQueryable<CustomerOrder> query)
{
return query;
}
/// <summary>Initializes a new instance of the <see cref="CartOrderProviderByUser"/> class.</summary>
/// <param name="cookieManager">The cookie Manager.</param>
/// <param name="perRequestCacheManager">The per Request Cache Manager.</param>
/// <param name="unitOfWorkFactory">The unit Of Work Factory.</param>
/// <param name="customerOrderUtilities">The customer order utilities.</param>
/// <param name="cartSettings">The cart settings.</param>
public CartOrderProviderByUser(
ICookieManager cookieManager,
IPerRequestCacheManager perRequestCacheManager,
IUnitOfWorkFactory unitOfWorkFactory,
ICustomerOrderUtilities customerOrderUtilities,
CartSettings cartSettings)
{
this.CookieManager = cookieManager;
this.PerRequestCacheManager = perRequestCacheManager;
this.UnitOfWork = unitOfWorkFactory.GetUnitOfWork();
this.CustomerOrderUtilities = customerOrderUtilities;
this.CartSettings = cartSettings;
}
/// <summary>The get cart order.</summary>
/// <returns>The <see cref="CustomerOrder"/>.</returns>
public virtual CustomerOrder GetCartOrder()
{
var customerOrder = this.LookupCustomerOrder();
if (customerOrder != null && customerOrder.Status == CustomerOrder.StatusType.AwaitingApproval)
{
return customerOrder;
}
if (customerOrder == null || (customerOrder.Status != CustomerOrder.StatusType.Cart && customerOrder.Status != CustomerOrder.StatusType.PunchOut))
{
return null;
}
var currentUserProfile = SiteContext.Current.UserProfile ?? SiteContext.Current.RememberedUserProfile;
if (customerOrder.PlacedByUserProfile != currentUserProfile)
{
customerOrder.InitiatedByUserProfileId = currentUserProfile?.Id;
customerOrder.InitiatedByUserProfile = currentUserProfile;
customerOrder.PlacedByUserProfileId = currentUserProfile?.Id;
customerOrder.PlacedByUserProfile = currentUserProfile;
customerOrder.PlacedByUserName = currentUserProfile?.UserName ?? string.Empty;
}
this.SetCartOrder(customerOrder);
return customerOrder;
}
/// <summary>The get or create cart order.</summary>
/// <returns>The <see cref="CustomerOrder"/>.</returns>
public virtual CustomerOrder GetOrCreateCartOrder()
{
var customerOrder = this.GetCartOrder();
if (customerOrder != null)
{
return customerOrder;
}
customerOrder = this.CreateCartOrder();
this.SetCartOrder(customerOrder);
return customerOrder;
}
/// <summary>The set cart order.</summary>
/// <param name="customerOrder">The customer order.</param>
public virtual void SetCartOrder(CustomerOrder customerOrder)
{
this.PerRequestCacheManager.Add(CustomerOrderKey, customerOrder);
var userProfile = SiteContext.Current.UserProfile ?? SiteContext.Current.RememberedUserProfile;
if (userProfile == null)
{
if (customerOrder == null)
{
this.CookieManager.Remove(this.CartCookieName);
}
else
{
var expires = this.CartRetentionDays > 0 ? customerOrder.OrderDate.AddDays(this.CartRetentionDays) : (DateTimeOffset?)null;
this.CookieManager.Add(this.CartCookieName, customerOrder.Id.ToString(), expires);
}
}
}
/// <summary>Clears the cache.</summary>
public virtual void ClearCache()
{
this.PerRequestCacheManager.Remove(CustomerOrderKey);
}
/// <summary>The create cart order.</summary>
/// <returns>The <see cref="CustomerOrder"/>.</returns>
protected virtual CustomerOrder CreateCartOrder()
{
var customerOrderRepository = this.UnitOfWork.GetRepository<CustomerOrder>();
var customerOrder = customerOrderRepository.Create();
customerOrder.Status = CustomerOrder.StatusType.Cart;
customerOrder.OrderNumber = Guid.NewGuid().ToString();
var currentCustomer = SiteContext.Current.BillTo;
if (currentCustomer == null)
{
customerOrder.Customer = this.GetAbandonedCartCustomer();
this.CustomerOrderUtilities.SetBillTo(customerOrder, customerOrder.Customer);
}
else
{
customerOrder.Customer = currentCustomer;
this.CustomerOrderUtilities.SetBillTo(customerOrder, customerOrder.Customer);
customerOrder.ShipTo = SiteContext.Current.ShipTo;
this.CustomerOrderUtilities.SetShipTo(customerOrder, customerOrder.ShipTo);
}
var currentUserProfile = SiteContext.Current.UserProfile ?? SiteContext.Current.RememberedUserProfile;
customerOrder.InitiatedByUserProfile = currentUserProfile;
customerOrder.InitiatedByUserProfileId = currentUserProfile?.Id;
customerOrder.PlacedByUserProfile = currentUserProfile;
customerOrder.PlacedByUserProfileId = currentUserProfile?.Id;
customerOrder.PlacedByUserName = currentUserProfile?.UserName ?? string.Empty;
customerOrder.Type = CustomerOrder.OrderType.Order;
customerOrder.Website = this.UnitOfWork.GetRepository<Website>().Get(SiteContext.Current.WebsiteDto.Id);
customerOrder.WebsiteId = SiteContext.Current.WebsiteDto.Id;
var currency = SiteContext.Current?.CurrencyDto;
if (currency != null)
{
this.CustomerOrderUtilities.SetCurrency(customerOrder, currency.Id);
}
customerOrderRepository.Insert(customerOrder);
this.UnitOfWork.Save();
return customerOrder;
}
/// <summary>The get abandoned cart customer.</summary>
/// <returns>The <see cref="Customer"/>.</returns>
protected virtual Customer GetAbandonedCartCustomer()
{
var customerRepository = this.UnitOfWork.GetTypedRepository<ICustomerRepository>();
var customer = customerRepository.GetBillToByNumber(Customer.AbandonedCartNumber);
if (customer == null)
{
customer = customerRepository.Create();
customer.CustomerNumber = Customer.AbandonedCartNumber;
customer.IsBillTo = true;
customerRepository.Insert(customer);
this.UnitOfWork.Save();
}
return customer;
}
/// <summary>The lookup customer order.</summary>
/// <returns>The <see cref="CustomerOrder"/>.</returns>
protected virtual CustomerOrder LookupCustomerOrder()
{
var customerOrder = this.PerRequestCacheManager.Get<CustomerOrder>(CustomerOrderKey) ?? this.GetCustomerOrder();
customerOrder = this.ReplaceWithApprovalOrderIfNeeded(customerOrder);
this.PerRequestCacheManager.Add(CustomerOrderKey, customerOrder);
return customerOrder;
}
/// <summary>The get customer order.</summary>
/// <returns>The <see cref="CustomerOrder"/>.</returns>
protected virtual CustomerOrder GetCustomerOrder()
{
var currentUserProfile = SiteContext.Current.UserProfile ?? SiteContext.Current.RememberedUserProfile;
return currentUserProfile == null
? this.GetCustomerOrderForNotLoggedUser()
: this.GetCustomerOrderForLoggedInUser();
}
/// <summary>The get customer order for not logged user.</summary>
/// <returns>The <see cref="CustomerOrder"/>.</returns>
protected virtual CustomerOrder GetCustomerOrderForNotLoggedUser()
{
var customerOrderId = this.CookieManager.Get(this.CartCookieName);
return customerOrderId.IsBlank()
? null
: this.UnitOfWork.GetRepository<CustomerOrder>().Get(customerOrderId);
}
/// <summary>The get customer order for logged in user.</summary>
/// <returns>The <see cref="CustomerOrder"/>.</returns>
protected virtual CustomerOrder GetCustomerOrderForLoggedInUser()
{
if (this.KeepCartAfterLogin)
{
var customerOrderId = this.CookieManager.Get(this.CartCookieName);
if (!customerOrderId.IsBlank())
{
var customerOrder = this.UnitOfWork.GetRepository<CustomerOrder>().Get(customerOrderId);
if (customerOrder == null)
{
this.CookieManager.Remove(this.CartCookieName);
}
else
{
var currentUserProfile = SiteContext.Current.UserProfile ?? SiteContext.Current.RememberedUserProfile;
if (customerOrder.InitiatedByUserProfileId == currentUserProfile.Id)
{
this.CookieManager.Remove(this.CartCookieName);
var voidOldCarts = this.ApplyCustomerOrderBaseFilter(this.UnitOfWork.GetRepository<CustomerOrder>().GetTable());
this.ApplyCustomerOrderAdditionalFilter(voidOldCarts)
.Where(co => co.Id != customerOrder.Id)
.Each(co => co.Status = CustomerOrder.StatusType.Void);
}
return customerOrder;
}
}
}
var cart = this.ApplyCustomerOrderBaseFilter(this.UnitOfWork.GetRepository<CustomerOrder>().GetTable());
cart = this.ApplyCustomerOrderAdditionalFilter(cart);
return cart.OrderByDescending(co => co.CreatedOn).FirstOrDefault();
}
/// <summary>The replace with approval order if needed.</summary>
/// <param name="customerOrder">The customer order.</param>
/// <returns>The <see cref="CustomerOrder"/>.</returns>
protected virtual CustomerOrder ReplaceWithApprovalOrderIfNeeded(CustomerOrder customerOrder)
{
var cookieKey = SiteContext.Current.WebsiteDto.Id + "_CustomerOrderForApproval";
var customerOrderForApprovalId = this.CookieManager.Get(cookieKey);
if (customerOrderForApprovalId.IsBlank() || customerOrderForApprovalId.EqualsIgnoreCase(customerOrder?.Id.ToString()))
{
return customerOrder;
}
var customerOrderForApproval = this.UnitOfWork.GetRepository<CustomerOrder>().Get(customerOrderForApprovalId);
var userProfile = SiteContext.Current.UserProfile;
if (customerOrderForApproval == null || customerOrderForApproval.Status != CustomerOrder.StatusType.AwaitingApproval || userProfile == null)
{
this.CookieManager.Remove(cookieKey);
return customerOrder;
}
if (customerOrderForApproval.ApproverUserProfileId == userProfile.Id)
{
return customerOrderForApproval;
}
// if the user is not an Administrator, then they can only approve orders assigned to themselves
if (!SiteContext.Current.IsUserInRole(BuiltInRoles.Administrator))
{
return customerOrder;
}
// if the user is an Administrator, but does not have this billto assigned, return initial order
if (customerOrderForApproval.Customer.UserProfiles.All(m => m.Id != userProfile.Id))
{
return customerOrder;
}
// if the shipto is the billto, then the Administrative user has access
if (customerOrderForApproval.Customer.Id.Equals(customerOrderForApproval.ShipTo.Id))
{
return customerOrderForApproval;
}
// if the user is an Administrator and has no assigned shiptos, then they can approve any order for their billtos
var shipTos = this.UnitOfWork.GetTypedRepository<ICustomerRepository>().GetAssignedShipTos(customerOrderForApproval.Customer, userProfile.Id);
if (!shipTos.Any())
{
return customerOrderForApproval;
}
// if the user is an Administrator and has assigned shiptos, then they can only approve orders for their assigned shiptos
if (shipTos.Any(s => s.Id == customerOrderForApproval.ShipTo.Id))
{
return customerOrderForApproval;
}
return customerOrder;
}
}