2014-09-08 13 views
5

Desidero modificare un codice in un'azione dell'azione OpcSaveBilling da CheckoutController. Non voglio modificare il codice principale di NopCommerce, quindi ho bisogno di provare a sovrascrivere il codice con il mio codice personalizzato.Come implementare un filtro azione in NopCommerce

Ho letto questo articolo per iniziare http://www.pronopcommerce.com/overriding-intercepting-nopcommerce-controllers-and-actions. Da quello che ho letto, puoi eseguire il tuo codice prima che un'azione venga eseguita e dopo che un'azione è stata eseguita. Ma quello che non sto ottenendo è la parte che l'articolo sta lasciando aperto (il codice effettivo che deve essere eseguito).

Quello che voglio di base è la stessa funzione del codice originale ma con alcune modifiche personalizzate. Ho aggiunto una casella di controllo nella vista OnePageCheckout e in base a tale casella di controllo è necessario saltare la parte di invio degli indirizzi di spedizione nel checkout o meno. (Utilizzare l'indirizzo di fatturazione per l'indirizzo di spedizione)

Ho già aggiunto il codice nel codice principale e questo funziona e salta il passaggio (NOTA: so che devo ancora aggiungere manualmente l'indirizzo di fatturazione come indirizzo di spedizione) ma come ho detto non voglio alterare il codice nel nucleo di NopCommerce ma sovrascriverlo.

Se la mia domanda non è comprensibile e avete bisogno di più codice o spiegazione, sono lieto di fornire altro. Se il modo in cui sto facendo questo non è adatto per quello che voglio, sarei grato se me lo dica!

Il mio codice:

La classe Operazione filtro:

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

}

Registrato classe in DependencyRegistar nello stesso plugin Nop

builder.RegisterType<ShippingAddressOverideActionFilter>().As<System.Web.Mvc.IFilterProvider>(); 

Un esempio di lavoro con l'abitudine codice in esso. Ma questo è nell'azione principale.

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

risposta

6

Nessuno può dirti quello che è necessario mettere in OnActionExecuting, perché c'è così tanto si può fare in esso.

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 
    } 

Regola empirica? Scrivi un codice come se scriverai un'azione. L'unico ritocco è, invece di restituire ActionResult, è necessario impostare filterContext.Result (non è possibile restituire nulla in quanto si tratta di un metodo void).

Ad esempio, l'impostazione seguente reindirizzerà alla pagina iniziale prima di eseguire l'azione che si sta ignorando.

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

ricordare che questo è OnActionExecuting, quindi questo viene eseguito prima che l'azione si sta prevalente. E se lo reindirizza su un'altra pagina, non chiamerà l'azione che stai sovrascrivendo. :)

+1

Grazie per la risposta. Se avessi messo un reindirizzamento a un controller + un'azione personalizzata in là come nella risposta, c'è un modo per inviare il parametro FormCollection che l'OpcSaveBilling ottiene quando viene chiamato con quel reindirizzamento in modo da poter usare nella mia azione personalizzata? –

Problemi correlati