public ActionResult Purchase(CheckoutPage currentPage, CheckoutViewModel checkoutViewModel, IPaymentMethodViewModel <IPaymentOption> paymentViewModel) { // Since the payment property is marked with an exclude binding attribute in the CheckoutViewModel // it needs to be manually re-added again. checkoutViewModel.Payment = paymentViewModel; if (String.IsNullOrEmpty(checkoutViewModel.BillingAddress.Email)) { ModelState.AddModelError("BillingAddress.Email", _localizationService.GetString("/Shared/Address/Form/Empty/Email")); } if (checkoutViewModel.UseBillingAddressForShipment) { // If only the billing address is of interest we need to remove any existing error related to the // other shipping addresses. foreach (var state in ModelState.Where(x => x.Key.StartsWith("ShippingAddresses")).ToArray()) { ModelState.Remove(state); } } if (!ModelState.IsValid) { InitializeCheckoutViewModel(currentPage, checkoutViewModel); return(View("Index", checkoutViewModel)); } _checkoutService.ClearOrderAddresses(); // If the shipping address should be the same as the billing address, replace all existing shipping addresses to // be the same as the billing address instead. if (checkoutViewModel.UseBillingAddressForShipment) { checkoutViewModel.ShippingAddresses = new ShippingAddress[] { checkoutViewModel.BillingAddress }; } SaveBillingAddress(checkoutViewModel); SaveShippingAddresses(checkoutViewModel); _cartService.RunWorkflow(OrderGroupWorkflowManager.CartPrepareWorkflowName); _cartService.SaveCart(); try { _paymentService.ProcessPayment(checkoutViewModel.Payment.PaymentMethod); } catch (PreProcessException) { ModelState.AddModelError("PaymentMethod", _localizationService.GetString("/Checkout/Payment/Errors/PreProcessingFailure")); } if (!ModelState.IsValid) { InitializeCheckoutViewModel(currentPage, checkoutViewModel); return(View("Index", checkoutViewModel)); } return(Finish(currentPage)); }