Search code examples
c#asp.net-mvcinheritanceencapsulationcode-duplication

How should I encapsulate my MVC-Action in order to avoid code duplication?


I have two classes - MVC-Controlles in this particular case – that have one common controller action (a JSON action that will be called from JavaScript). Because of code duplication, I would like to put this action in a parent controller class. We already have a controller base class that inherits from Controller and is used as base class, with common functionality, from 6 other Controllers. My JSON action is actually common only for 2 controllers, so I think that it’s not a good idea to put my JSON action in the base controller that is already used by the other 6 controllers. Here’s the existing class hierarchy graph:

Existing Controller class hierarchy

Where should I put my JSON action in order to avoid code duplication? My idea is to inherit the class ControllerBase – let’s say ControllerBaseExtended – and to place my JSON action in here. So now, my 2 Controllers can inherit from ControllerBaseExtended instead of ControllerBase. This is how the class hierarchy would look like at the end:

Final Controller class hierarchy

Is there any better way to solve this problem?


Solution

  • Instead of creating another base controller, extract code from both actions into another class, e.g. JsonActionProcessor. Then you will need to call that implementation.

    public class JsonActionHelper
    {
        public JsonResult Something()
        {
            //do something common
            return new JsonResult();
        }
    }
    

    Then you can call it from your actions

    public JsonResult Action1()
    {
        return new JsonActionHelper().Something();
    }
    
    public JsonResult Action2()
    {
        return new JsonActionHelper().Something();
    }
    

    If you have UnitTests then you should extract interface from JsonActionHelper and inject it into your Controllers.

    However if you have 2 identical actions, why just not to have one action and call it via JavaScript from different views?