2014-09-08 9 views
5

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 }); 
     } 
    } 

Antwort

6

Niemand kann Ihnen sagen, was Sie in OnActionExecuting, setzen müssen, weil es so viel Sie in es tun können.

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 
    } 

Faustregel? Schreibe irgendeinen Code, wie du eine Action schreibst. Die einzige Optimierung ist, anstatt ActionResult zurückzugeben, sollten Sie filterContext.Result (Sie können nichts zurückgeben, da dies eine void Methode ist).

Wenn Sie beispielsweise Folgendes festlegen, wird auf die Startseite umgeleitet, bevor Sie die Aktion ausführen, die Sie überschreiben möchten.

filterContext.Result = new RedirectToRouteResult("HomePage", null); 

Denken Sie daran, dies ist OnActionExecuting, also wird dies vor der Aktion ausgeführt, die Sie überschreiben. Und wenn Sie es auf eine andere Seite umleiten, ruft es nicht die Aktion auf, die Sie außer Kraft setzen. :)

+1

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? –

Verwandte Themen