2014-09-08 12 views
5

Chcę zmienić kod w akcji akcji OpcSaveBilling z CheckoutController. Nie chcę zmieniać podstawowego kodu NopCommerce, więc muszę spróbować nadpisać kod przy pomocy własnego kodu niestandardowego.Jak zaimplementować filtr działania w NopCommerce

Przeczytałem ten artykuł, aby rozpocząć pracę z http://www.pronopcommerce.com/overriding-intercepting-nopcommerce-controllers-and-actions. Z tego, co przeczytałem, możesz wykonać swój własny kod przed wykonaniem akcji i po wykonaniu akcji. Ale to, czego nie otrzymuję, to część, którą artykuł pozostawia otwartą (rzeczywisty kod, który należy wykonać).

To, czego najbardziej chcę, to ta sama funkcja oryginalnego kodu, ale z pewnymi niestandardowymi poprawkami. Dodałem pole wyboru w widoku OnePageCheckout i na podstawie tego pola wyboru należy pominąć część dotyczącą adresu dostawy w kasie lub nie. (Użyj adresu rozliczeniowego dla adresu wysyłki)

Mam już ten kod dodany w kodzie źródłowym i tej pracy i pominie krok (UWAGA: Wiem, że muszę ręcznie dodać adres rozliczeniowy jako adres wysyłki) ale jak powiedziałem, nie chcę zmieniać kodu w rdzeniu NopCommerce, ale go zastąpić.

Jeśli moje pytanie nie jest zrozumiałe i potrzebujesz więcej kodu lub wyjaśnienia, chętnie udzielę więcej. Jeśli sposób, w jaki to robię, nie jest odpowiedni do tego, co chcę, byłbym wdzięczny, gdybyś mi powiedział!

Mój kod:

Klasa Działanie filtra:

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

}

zarejestrowała klasę w DependencyRegistar w tej samej wtyczce NOP

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

przykładem pracy z obyczajem w nim kod. Ale to jest w akcji podstawowej.

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

Odpowiedz

6

Nikt nie powie Ci, co musisz umieścić w OnActionExecuting, ponieważ jest w nim tyle możliwości.

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 
    } 

Zasada? Napisz dowolny kod, na przykład w jaki sposób napiszesz akcję. Jedynym usprawnieniem jest to, że zamiast zwracać ActionResult, powinieneś ustawić filterContext.Result (nie możesz zwrócić niczego, ponieważ jest to metoda void).

Na przykład ustawienie następujących opcji spowoduje przekierowanie do strony głównej przed wykonaniem czynności, którą nadpisujesz.

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

Pamiętaj, że jest to OnActionExecuting, więc jest to wykonywane przed Akcja, którą nadpisujesz. A jeśli przekierujesz go na inną stronę, nie wywoła to Akcji, którą nadpisujesz. :)

+1

Dziękuję za odpowiedź. Gdybym umieścił przekierowanie do niestandardowego kontrolera + akcji, tak jak w Twojej odpowiedzi, czy istnieje sposób na wysłanie parametru FormCollection, który uzyskuje OpcSaveBilling, gdy zostanie wywołany z tym przekierowaniem, aby móc go użyć w mojej niestandardowej akcji? –

Powiązane problemy