Update ShoppingCart / Remove Cache?

Delford Chaffin asked on March 8, 2016 20:45

I'm build a reserved ticket system and I need tickets to expire after 15 minutes if they are left in a cart. I have written a scheduled task and can delete the line items from the COM_ShoppingCartSKU, but it doesn't reflect on the Shopping Cart page. Is this shopping cart content cached? If so, how can I clear that cache.

Relevant Code:

public string Execute(TaskInfo ti)
{
    try
    {
        string _expWhere = String.Format("CartItemValidTo < '{0}' AND SKUID IN ({1})", DateTime.Now, _ticketSKUs);
        InfoDataSet<ShoppingCartItemInfo> allItems = ShoppingCartItemInfoProvider.GetShoppingCartItems(_expWhere, null);

        foreach (ShoppingCartItemInfo _item in allItems)
        {
            ShoppingCartInfo _cart = getCart(_item);
            _cart.RemoveShoppingCartItem(_item.CartItemGUID);
            _item.Delete();
            _cart.SubmitChanges(false);
        }
    }
    catch (Exception ex)
    {
        // Log Exception
    }
    return null;
}

private ShoppingCartInfo getCart(ShoppingCartItemInfo item)
{
    ShoppingCartInfo _cart = item.ShoppingCart;
    if (_cart.ShoppingCartID == 0)
    {
        _cart = ShoppingCartInfoProvider.GetShoppingCartInfo(item.ShoppingCartID);
    }
    return _cart;
}

When I used just "item.ShoppingCart" to get the cart, it deleted the items from COM_ShoppingCartSKU, but it seemed like it didn't always get the proper shopping cart, but would create a new cart record. So, I created the "getCart" function to get the cart two different ways. This seems hack-ish to me and I'd rather "item.ShoppingCart" just get the correct cart.

Bottom line, my getCart function ensures I always have the proper cart (verified by logging ID - not shown in code), but the items still show on the web site as being in the cart even though they are not in the database table.

If I restart the application, the temporary cart goes away, but it does not if I simply clear the cache. So ... how do I get rid of this cached shopping cart?

Oh ... and if I run this code just on a page (not in the scheduled task), it works correctly.

Help.

Thanks!

Recent Answers


Trevor Fayas answered on March 8, 2016 20:58

Carts can be a bit of a hassle to manage, since the in memory doesn't always sync with the database, or vice versa. You have to really do the operation on both.

Below is a script i have that removes both from database and memory, should be able to use it to do what you need to:

        // Get Cart
        var cart = ECommerceContext.CurrentShoppingCart;

        if (cart != null)
        {
            // Gets the first item matching the product in the current shopping cart
            var MembershipItems = ShoppingCartItemInfoProvider.GetShoppingCartItems()
                                                    .WhereIn("SKUID", SkuIDs)
                                                    .WhereEquals("ShoppingCartID", cart.ShoppingCartID).ToList();

            foreach (var item in MembershipItems)
            {
                // Removes the item from the shopping cart Memory
                cart.RemoveShoppingCartItem(item.CartItemID);

                // Removes the item from the database
                ShoppingCartItemInfoProvider.DeleteShoppingCartItemInfo(item);
            }
        }
0 votesVote for this answer Mark as a Correct answer

Delford Chaffin answered on March 8, 2016 21:34

I incorporated the:

ShoppingCartItemInfoProvider.DeleteShoppingCartItemInfo(item);

... line into my code, but it still, when I go to the browser, shows those items as being in the cart even though they are not in my database. They must be in memory somewhere and that somewhere is not affected from the Scheduled Task the same way as it is on the page. I guess the context is different, but I would think calling the cart by its ID wouldn't matter about context, but I somehow need to affect the version of the cart in memory as well.

0 votesVote for this answer Mark as a Correct answer

Delford Chaffin answered on March 8, 2016 23:04

I should also mention this is Kentico 7.

0 votesVote for this answer Mark as a Correct answer

Zdeněk Cetkovský answered on March 9, 2016 21:22

Hi,

Trevor's script is correct; I would recommend to use API with our provider methods for all operations... however, in this case, it still isn't enough. To put it more simply, the visitor's shopping cart object is primarily saved as a session variable, which means that there's no direct access to it from different request (which the scheduled task typically runs within). Even if you remove the items from DB or using API, the controls or web parts that display the cart content still use the data from session of the visitor - customer.

If you remove an item from the cart outside the session, any change that you make to the shopping cart object will be saved to the database and the application cache, however it will not be visible to the customer until their shopping cart is reloaded. This is because all of the live site web parts or controls will still keep the previous instance of the shopping cart in the session variable.

Unfortunately there is no example of clearing the shopping cart active in different session available. This scenario is rather uncommon, so it is not yet covered by our documentation or knowledge base. Currently (and in version 7), the only way to achieve the scenario is to either ensure your code uses the visitor's session, or develop a clearing mechanism that will detect your changes and reload the EcommerceContext.CurrentShoppingCart property.

One possible way (actually used by one of our customers) could be creating a custom table and write cart IDs into there from the scheduled task. Then you could check those values in the web parts (version 8+) or controls (which display cart content) if the current cart id exists in the table, and optionally empty the session variable. I would just add that in version 7 you can detect the changes in visitor's context running code e.g. in the ShoppingCart.ascx control or similarly in relevant places (where cart content or data are displayed, or loaded).

In later 8.2 version and in 9, it should be possible to implement this more systematically using custom provider (where querying the CurrentShoppingCart from ECommerceContext could be customized). Furthermore, we will be probably moving away from session storage to universal Kentico caching mechanisms for shopping cart object in next version, so it should be easier to cover similar external shoping cart update scenarios in the future.

Regards, Zdenek

0 votesVote for this answer Mark as a Correct answer

Delford Chaffin answered on March 10, 2016 15:28

I ended up going with a hybrid solution of this and then an event on ShoppingCart update that ran the same test against the cart items and deleted them and redirected the user back to the cart with a message that some of their items had expired/been removed. The scheduled task still frees up the tickets for other users.

0 votesVote for this answer Mark as a Correct answer

   Please, sign in to be able to submit a new answer.