Ich möchte einige Code in einer Aktion der Aktion OpcSaveBilling von der CheckoutController ändern. Ich möchte den Kerncode von NopCommerce nicht ändern, also muss ich versuchen, den Code mit meinem eigenen benutzerdefinierten Code zu übersteuern.So implementieren Sie einen Aktionsfilter in NopCommerce
Ich habe diesen Artikel gelesen, um mich zu starten http://www.pronopcommerce.com/overriding-intercepting-nopcommerce-controllers-and-actions. Von dem, was ich gelesen habe, können Sie Ihren eigenen Code ausführen, bevor eine Aktion ausgeführt wird und nachdem eine Aktion ausgeführt wurde. Aber was ich nicht bekomme, ist der Teil, den der Artikel offen lässt (der eigentliche Code, der ausgeführt werden muss).
Was ich grundsätzlich möchte, ist die gleiche Funktion des ursprünglichen Codes, aber mit einigen benutzerdefinierten Verbesserungen. Ich habe ein Kontrollkästchen in der OnePageCheckout-Ansicht hinzugefügt und basierend auf diesem Kontrollkästchen muss der Eingabe-Lieferadresse-Teil in der Kasse übersprungen werden oder nicht. (Verwenden Sie die Rechnungsadresse für die Lieferadresse)
Ich habe bereits diesen Code im Kern-Code hinzugefügt und das funktioniert und überspringt den Schritt (HINWEIS: Ich weiß, ich muss noch manuell die Rechnungsadresse als Lieferadresse hinzufügen) Aber wie ich schon sagte, ich möchte den Code im Kern von NopCommerce nicht ändern, sondern ihn außer Kraft setzen.
Wenn meine Frage nicht verständlich ist und Sie mehr Code oder Erklärung benötigen, bin ich glücklich, mehr zur Verfügung zu stellen. Wenn die Art, wie ich das tue, nicht für das geeignet ist, was ich will, würde ich mich freuen, wenn du es mir sagst!
Mein Code:
Der Aktionsfilterklasse:
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)
{
// What do I put in here? So that I have the code of the core action but with my custom tweaks in it
}
}
}
die Klasse in DependencyRegistar im gleichen Nop-Plugin Registrierte
builder.RegisterType<ShippingAddressOverideActionFilter>().As<System.Web.Mvc.IFilterProvider>();
Ein Arbeitsbeispiel mit benutzerdefinierten Code darin. Aber das ist in der Kernaktion.
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's 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 });
}
}
Vielen Dank für Ihre Antwort. Wenn ich eine Umleitung auf eine benutzerdefinierte Steuerung + Aktion wie in Ihrer Antwort einfügen würde, gibt es eine Möglichkeit, den FormCollection-Parameter zu senden, den OpcSaveBilling beim Aufruf mit dieser Umleitung erhält, damit ich ihn in meiner benutzerdefinierten Aktion verwenden kann? –