public CartContext Apply(PreCheckoutRuleContext context)
        {
            var shippingAddress = EffectiveShippingAddressProvider.GetEffectiveShippingAddress(context.Customer);

            var availableShippingMethods = CachedShippingMethodCollectionProvider
                                           .Get(context.Customer, shippingAddress, context.CartContext.Cart.CartItems, AppLogic.StoreID());

            // If there are no available shipping methods, the customer hasn't selected one, or the customer selected an invalid one, selectedShipping will be null.
            var selectedShippingMethod = availableShippingMethods
                                         .Where(shippingMethod => shippingMethod.Id == context.PersistedCheckoutContext.SelectedShippingMethodId)
                                         .FirstOrDefault();

            // No matter what shipping method was selected but the customer, if there is only one available shipping method, set the customers selection to it.
            if (availableShippingMethods.Count() == 1)
            {
                selectedShippingMethod = availableShippingMethods.First();
            }

            // Update all cart items to the updated selection. If the selection is null, then it clears the selection from the cart items and the customer has to select a new one.
            ShippingMethodCartItemApplicator.UpdateCartItemsShippingMethod(
                context.Customer,
                context.CartContext.Cart,
                selectedShippingMethod);

            return(new CartContext(
                       cartContext: context.CartContext,
                       cart: CachedShoppingCartProvider.Get(context.Customer, CartTypeEnum.ShoppingCart, AppLogic.StoreID())));
        }
        void SetShippingMethod(ShippingMethod shippingMethod, ShoppingCart cart, Customer customer)
        {
            int    shippingMethodId;
            string shippingMethodNameForDatabase;

            if (cart.ShippingIsFree &&
                !AppLogic.AppConfigBool("FreeShippingAllowsRateSelection") &&
                !AppLogic
                .AppConfig("ShippingMethodIDIfFreeShippingIsOn")
                .ParseAsDelimitedList <int>()
                .Contains(shippingMethod.Id))
            {
                shippingMethodId = 0;
                shippingMethodNameForDatabase = string.Format(
                    "{0} : {1}",
                    "FREE",
                    cart.GetFreeShippingReason());
            }
            else
            {
                shippingMethodId = shippingMethod.Id;
                shippingMethodNameForDatabase = Shipping.GetActiveShippingCalculationID() != Shipping.ShippingCalculationEnum.UseRealTimeRates
                                        ? Shipping.GetShippingMethodDisplayName(shippingMethod.Id, null)
                                        : Shipping.GetFormattedRealTimeShippingMethodForDatabase(shippingMethod.Name, shippingMethod.Freight, shippingMethod.VatRate);
            }

            // Update the persisted checkout context
            var checkoutContext = PersistedCheckoutContextProvider.LoadCheckoutContext(customer);

            PersistedCheckoutContextProvider.SaveCheckoutContext(
                customer,
                new PersistedCheckoutContext(
                    creditCard: checkoutContext.CreditCard,
                    payPalExpress: checkoutContext.PayPalExpress,
                    purchaseOrder: checkoutContext.PurchaseOrder,
                    braintree: checkoutContext.Braintree,
                    amazonPayments: checkoutContext.AmazonPayments,
                    termsAndConditionsAccepted: checkoutContext.TermsAndConditionsAccepted,
                    over13Checked: checkoutContext.Over13Checked,
                    shippingEstimateDetails: checkoutContext.ShippingEstimateDetails,
                    offsiteRequiresBillingAddressId: checkoutContext.OffsiteRequiresBillingAddressId,
                    offsiteRequiresShippingAddressId: checkoutContext.OffsiteRequiresShippingAddressId,
                    email: checkoutContext.Email,
                    selectedShippingMethodId: shippingMethodId));

            // Update the database for legacy cases
            ShippingMethodCartItemApplicator.UpdateCartItemsShippingMethod(customer, cart, shippingMethod);
        }
        void SetShippingMethod(ShippingMethod shippingMethod, ShoppingCart cart, Customer customer)
        {
            int    shippingMethodId;
            string shippingMethodNameForDatabase;

            if (cart.ShippingIsFree &&
                !AppConfigProvider.GetAppConfigValue <bool>("FreeShippingAllowsRateSelection") &&
                !AppLogic
                .AppConfig("ShippingMethodIDIfFreeShippingIsOn")
                .ParseAsDelimitedList <int>()
                .Contains(shippingMethod.Id))
            {
                shippingMethodId = 0;
                shippingMethodNameForDatabase = string.Format(
                    "{0} : {1}",
                    StringResourceProvider.GetString("shoppingcart.aspx.16"),
                    cart.GetFreeShippingReason());
            }
            else
            {
                shippingMethodId = shippingMethod.Id;
                shippingMethodNameForDatabase = Shipping.GetActiveShippingCalculationID() != Shipping.ShippingCalculationEnum.UseRealTimeRates
                                        ? Shipping.GetShippingMethodDisplayName(shippingMethod.Id, null)
                                        : Shipping.GetFormattedRealTimeShippingMethodForDatabase(shippingMethod.Name, shippingMethod.Freight, shippingMethod.VatRate);
            }

            // Update the persisted checkout context
            PersistedCheckoutContextProvider.SaveCheckoutContext(
                customer,
                new PersistedCheckoutContextBuilder()
                .From(PersistedCheckoutContextProvider.LoadCheckoutContext(customer))
                .WithSelectedShippingMethodId(shippingMethodId)
                .Build());

            // Update the database for legacy cases
            ShippingMethodCartItemApplicator.UpdateCartItemsShippingMethod(customer, cart, shippingMethod);
        }