2014-09-08 2 views
5

CheckoutController에서 OpcSaveBilling 액션의 액션에서 일부 코드를 변경하고 싶습니다. NopCommerce의 핵심 코드를 변경하지 않고 자체 사용자 정의 코드로 코드를 덮어 써야합니다.NopCommerce에서 액션 필터를 구현하는 방법

나는이 기사를 읽고 나를 시작했다. http://www.pronopcommerce.com/overriding-intercepting-nopcommerce-controllers-and-actions. 내가 읽은 바로는 액션이 ​​실행되기 전에 액션이 실행 된 후에 자신의 코드를 실행할 수 있습니다. 하지만 내가 얻지 못하는 부분은 기사가 공개되고있는 부분 (실행해야하는 실제 코드)입니다.

내가 기본적으로 원하는 것은 원본 코드와 동일한 기능이지만 일부 맞춤 설정이 있습니다. OnePageCheckout보기에 체크 박스를 추가했으며 해당 체크 박스를 기반으로 체크 아웃에서 배송 주소 입력 부분을 건너 뛸 필요가 있습니다. (배송지 주소로 청구서 수신 주소 사용)

이미 코드가 핵심 코드와이 작업에 추가되어 있으며 단계를 건너 뛰었습니다 (참고 : 청구 주소를 배송지 주소로 수동으로 추가해야 함) 하지만 내가 말했듯이 나는 NopCommerce의 핵심 부분에서 코드를 변경하고 싶지는 않지만 그것을 덮어 쓰겠다고 말했다.

내 질문에 이해할 수없고 더 많은 코드 또는 설명이 필요한 경우 더 자세히 제공해 드리겠습니다. 내가하는 일이 내가 원하는 것에 어울리지 않는다면, 말해 주시면 감사하겠습니다!

내 코드 :

액션 필터 클래스 :

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

}

같은 Nop는 플러그인에 DependencyRegistar의 클래스를 등록

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

정의와 동작하는 예제 그 안에 코드. 그러나 이것은 핵심 행동에 있습니다.

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

답변

6

아무도 그렇게 당신이 그것에 할 수 있기 때문에 당신이 OnActionExecuting에 둘 필요가 무엇을 말할 수 있습니다.

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 
    } 

엄폐 법칙? 액션 작성 방법과 같은 코드를 작성하십시오. 유일한 비틀기는 ActionResult를 반환하는 대신 filterContext를 설정해야합니다. (void 메서드이므로 아무 것도 반환 할 수 없습니다.)

예를 들어 다음을 설정하면 재정의하려는 작업을 실행하기 전에 홈 페이지로 리디렉션됩니다.

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

이것은 OnActionExecuting이므로이를 재정의하려는 작업 전에 실행해야합니다. 다른 페이지로 리디렉션하면 재정의 할 액션이 호출되지 않습니다. :)

+1

답장을 보내 주셔서 감사합니다. 회신에 사용자 지정 컨트롤러 + 동작에 리디렉션을 넣으려면 해당 사용자 지정 동작에서 사용할 수 있도록 OpcSaveBilling이 리디렉션과 함께 호출 될 때 FormCollection 매개 변수를 보내는 방법이 있습니까? –

관련 문제