I want to change some code in the action action of the OpcSaveBilling from CheckoutController. I donβt want to change the main NopCommerce code, so I need to try to redefine the code using my own code.
I read this article to get started http://www.pronopcommerce.com/overriding-intercepting-nopcommerce-controllers-and-actions . From what I read, you can execute your own code before the action is completed and after the action is completed. But what I am not getting is that the article remains open (the actual code that needs to be executed).
What I basically want is the same source code features, but with some user preferences. I added a flag in the OnePageCheckout view and based on this flag, he needs to skip part of the incoming delivery addresses at the box office or not. (Use billing address for shipping address)
I already have the code added to the main code and this work and will skip this step (NOTE: I know that I still need to manually add the billing address as the delivery address), but as I said, I donβt want to change code in the core of NopCommerce, but override it.
If my question is incomprehensible and you need more code or explanations, I gladly provided more. If the way I do this is not suitable for what I want, I would appreciate it if you told me.
My code is:
Action Filter Class:
using Nop.Web.Controllers; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Web.Mvc; namespace Nop.Plugin.Misc.MyProject.ActionFilters { class ShippingAddressOverideActionFilter : ActionFilterAttribute, IFilterProvider { public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) { if (controllerContext.Controller is CheckoutController && actionDescriptor.ActionName.Equals("OpcSaveBilling", StringComparison.InvariantCultureIgnoreCase)) { return new List<Filter>() { new Filter(this, FilterScope.Action, 0) }; } return new List<Filter>(); } public override void OnActionExecuting(ActionExecutingContext filterContext) {
}
Registered a class in DependencyRegistar in the same Nop plugin
builder.RegisterType<ShippingAddressOverideActionFilter>().As<System.Web.Mvc.IFilterProvider>();
Working example with custom code. But this is the main action.
public ActionResult OpcSaveBilling(FormCollection form) { try { //validation var cart = _workContext.CurrentCustomer.ShoppingCartItems .Where(sci => sci.ShoppingCartType == ShoppingCartType.ShoppingCart) .Where(sci => sci.StoreId == _storeContext.CurrentStore.Id) .ToList(); if (cart.Count == 0) throw new Exception("Your cart is empty"); if (!UseOnePageCheckout()) throw new Exception("One page checkout is disabled"); if ((_workContext.CurrentCustomer.IsGuest() && !_orderSettings.AnonymousCheckoutAllowed)) throw new Exception("Anonymous checkout is not allowed"); int billingAddressId = 0; int.TryParse(form["billing_address_id"], out billingAddressId); if (billingAddressId > 0) { //existing address var address = _workContext.CurrentCustomer.Addresses.FirstOrDefault(a => a.Id == billingAddressId); if (address == null) throw new Exception("Address can't be loaded"); _workContext.CurrentCustomer.BillingAddress = address; _customerService.UpdateCustomer(_workContext.CurrentCustomer); } else { //new address var model = new CheckoutBillingAddressModel(); TryUpdateModel(model.NewAddress, "BillingNewAddress"); //validate model TryValidateModel(model.NewAddress); if (!ModelState.IsValid) { //model is not valid. redisplay the form with errors var billingAddressModel = PrepareBillingAddressModel(selectedCountryId: model.NewAddress.CountryId); billingAddressModel.NewAddressPreselected = true; return Json(new { update_section = new UpdateSectionJsonModel() { name = "billing", html = this.RenderPartialViewToString("OpcBillingAddress", billingAddressModel) }, wrong_billing_address = true, }); } //try to find an address with the same values (don't duplicate records) var address = _workContext.CurrentCustomer.Addresses.ToList().FindAddress( model.NewAddress.FirstName, model.NewAddress.LastName, model.NewAddress.PhoneNumber, model.NewAddress.Email, model.NewAddress.FaxNumber, model.NewAddress.Company, model.NewAddress.Address1, model.NewAddress.Address2, model.NewAddress.City, model.NewAddress.StateProvinceId, model.NewAddress.ZipPostalCode, model.NewAddress.CountryId); if (address == null) { //address is not found. let create a new one address = model.NewAddress.ToEntity(); address.CreatedOnUtc = DateTime.UtcNow; //some validation if (address.CountryId == 0) address.CountryId = null; if (address.StateProvinceId == 0) address.StateProvinceId = null; if (address.CountryId.HasValue && address.CountryId.Value > 0) { address.Country = _countryService.GetCountryById(address.CountryId.Value); } _workContext.CurrentCustomer.Addresses.Add(address); } _workContext.CurrentCustomer.BillingAddress = address; _customerService.UpdateCustomer(_workContext.CurrentCustomer); } // Get value of checkbox from the one page checkout view var useSameAddress = false; Boolean.TryParse(form["billing-address-same"], out useSameAddress); // If it is checked copy the billing address to shipping address and skip the shipping address part of the checkout if (useSameAddress) { var shippingMethodModel = PrepareShippingMethodModel(cart); return Json(new { update_section = new UpdateSectionJsonModel() { name = "shipping-method", html = this.RenderPartialViewToString("OpcShippingMethods", shippingMethodModel) }, goto_section = "shipping_method" }); } // If it isn't checked go to the enter shipping address part of the checkout else { if (cart.RequiresShipping()) { //shipping is required var shippingAddressModel = PrepareShippingAddressModel(prePopulateNewAddressWithCustomerFields: true); return Json(new { update_section = new UpdateSectionJsonModel() { name = "shipping", html = this.RenderPartialViewToString("OpcShippingAddress", shippingAddressModel) }, goto_section = "shipping" }); } else { //shipping is not required _genericAttributeService.SaveAttribute<ShippingOption>(_workContext.CurrentCustomer, SystemCustomerAttributeNames.SelectedShippingOption, null, _storeContext.CurrentStore.Id); //load next step return OpcLoadStepAfterShippingMethod(cart); } } } catch (Exception exc) { _logger.Warning(exc.Message, exc, _workContext.CurrentCustomer); return Json(new { error = 1, message = exc.Message }); } }