Search code examples
controllerasp.net-core-webapi.net-6.0httpcontext

Extract common functionality from controller


I am unable to decide the best way to extract some functionality being used by multiple methods of multiple controller in my project

Common functionality

var myId = httpContext?.User.Claims.FirstOrDefault(x => x.Type == "myId")?.Value;
//few operations and a couple of repository calls
//return the details

Now I am wondering should I move it to base controller? Should I create a static helper class? What is the best way to handle this?

Edit 1: My attempt at resolving this:

public static class MyHelper
{   
    public static MyEntity? MyMethod(HttpContext httpContext, IMyRepo1 myRepo1,
        IMyRepo2 myRepo2)
    {
        var id = httpContext?.User.Claims.FirstOrDefault(c => c.Type == "myId")?.Value;
        var a = _myRepo1.CallRepo1Method(); 
    //random local operations on var a 
    var result = _myRepo2.CallRepo2Method();
    return result;
    }
}

//Call from controller
var result = MyHelper.MyMethod(HttpContext, _myRepo1, _myRepo2);

Solution

  • In my humble opinion, we should design the app to avoid high coupling, that means the query method should be based on the tables but not be based on the business for query requirement. I think the most ideal scenario is that, one table have a query sentence, and whenever a business is associate to this table, then using this query, and I also know in some terms it's impossible because our business is becoming more and more complex.

    Let's coming back to your scenario, as far as I know, we can certainly define a controller to have the httpContext and then do a lot of query, then inject this controller into some other controllers or services, but I don't think it's a very good idea to combine so many logic into the controller, we should put the logic into Services and in controller, we call multiple services at most.

    So if I were you, I will have a Service which received the myId, and execute one database query. If there were several database queries, then do all of them inside this service, if there were already existing several services for the database queries, then I might call the services one by one in the controller.

    public class CountryController : Controller
    {
        private readonly IMyHelper _myHelper;
        public CountryController(IMyHelper myHelper) { 
            _myHelper = myHelper;
        }
        public IActionResult Index()
        {
            var model = new CountryViewModel();
            var date = _myHelper.operateRepo("myid");
            return View(model);
        }
    }
    
    public class MyHelper : IMyHelper
    {
        private readonly ILogger<MyHelper> _logger;
        private readonly IRepoOne _repoOne;
        private readonly IRepoTwo _repoTwo;
    
        public MyHelper(ILogger<MyHelper> logger, IRepoOne repoOne, IRepoTwo repoTwo) {
            _logger = logger;
            _repoOne = repoOne;
            _repoTwo = repoTwo;
        }
        public string operateRepo(string id)
        {
            var res = _repoOne.xxmethod();
            //some operation on res here
            var res2 = _repoTwo.yymethod();
            //some opeartation here
            return "done";
        }
    }