Pages - Menu

nopCommerce - Create Customized Service that inherit from Core Service by Dependency Injection

Scope

Provide the cleanest way to inherit from nopCommerce core services without any tampering to the core files.

In this exercise, the Nop.Services project is 100% untouched. Why is it so important? It benefits in many different ways but mostly for the reason of keeping the code neat and manageable. A nice and clear separation between custom code and core code.

This is written base on nopCommerce 3.1, the latest version as of today it is written.

Business Requirements


  • Discount should be calculated based on RRP (Product.Price), not the SpecialPrice or TierPrice. 
  • PriceCalculationService.GetFinalPrice() should still return the cheapest price out of the following 3 conditions:-
    • Cheapest discount off RRP
    • Special Price
    • Tier Price (if eligible / available)

Setup

We setup the price for the "Cooking for Two" book as follow. RRP $19, and Speical $15.



 We then apply discount rule 50% to the category.


50% discount applied to special price and now selling for $7.5. This is the default behavior of nopCommerce out of the box.


Implementation

I created a new project and added to the solution called TA.Services. It follows the same folder structure as Nop.Services and I created a new class CustomPriceCalculationService.



In TA.Services, I added reference Nop.Core and Nop.Services.



Similarly, in Nop.Web.Framework, I need to add reference to TA.Services.

Under Nop.Web.Framework, I changed this magic line in DependencyRegistrar.cs.

[EDIT] In TA.Services, I create a new DependencyRegistrar that implements IDependencyRegistrar. I will register my service to the interface. What it does is now everywhere in the project that require IPriceCalculationService, the IoC will return a concrete class CustomPriceCalculationService instead of the old PriceCalculationService.




In CustomPriceCalculationService, I need to inherit PriceCalculationService and implement IPriceCalculationService. Some usual Ctor methods override.

For those who interested in the actual implementation, I only made small changes to GetDiscountAmount and GetFinalPrice.




Now we are selling for $9.5 (50% off from $19). Hopefully still a happy customer!!


Conclusion

There are maybe better ways to implement this than what I have done here. eg. Use the plugin approach and make the use of Special Price configurable in the admin etc, but I couldn't wait to try this 100% clean way of customizations. 

Now I have a complete control on how I like to plug and play this customizations in a multi-tenant environment, or I can put more custom inheritance on top of already custom inheritance. The only thing I need to change is the DI which is pretty much given. 

As you can see, customization on services is a lot easier than controllers. Note how much troubles I had with the nopCommerce Customization with Controller Inheritance.

5 comments:

  1. Hi Sunny,

    You are the best !!!!

    You found really perfect way to do customization considering future enhancement.. Moreover this will be very easy play with our customized code files.

    I followed above steps and added one entity (Table with CRUD) from Library Project to Presentation layer and all went very well.

    Again Thanks a lot for this solution and I really appreciate a lot.

    -Thanks,
    Deep.

    ReplyDelete
  2. Hi Sunny

    I have the nearly the same problem as you solved above. I'm not very familar with nopcommerce, so i have build a service like your description.

    - new project in nopcommerce\libraries called xyz.Services
    - new folder called Catalog in xyz.Services
    - generated a DependencyRegistrar.cs in main folder xyz.Services (added more using directives then in your description)
    - new programm CustomPriceService.cs in folder Catalog as your description

    After creating project I get a .dll call xyz.Services.

    Now, where do I put this .dll? How would nopcommerce take notice about the new .dll? If I put it in the nopcommerce\bin - folder, nothing happens.

    I would be very glad if you could help me! Thank you in advance.
    Wolfgang

    ReplyDelete
  3. Hi Wolfgang,

    Sorry for the late reply. What you have done is correct, the only missing bit is the Nop.Web needs to reference Ta.Services just like the way how it references Nop.Services. Presentation layer references to everything.

    Sunny

    ReplyDelete
  4. Hello Sunny.

    I realize it has been a while since you posted this, but I would like to know if you could give me advice on this.

    I would like to override the ImportManager.cs in Nop.Services\ExportImport. I want to change some of the coding in the method ImportProductsFromXlsx.

    Will your method of modifying that service work?

    Also, should I call the newly created ImportManager from a plugin?

    Any help that you can provide would be gratefully appreciated.

    Thanks,
    Tony

    ReplyDelete
    Replies
    1. Will your method of modifying that service work?
      Yes, you register a customService via Autofac and any code that reference to that interface will pick up the right instance of the object.


      Also, should I call the newly created ImportManager from a plugin?
      You can. That's how it works.

      Delete