Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Massive controller constructor argument list when using DI in MVC

I am working on ASP.NET MVC3 solution that uses dependency injection with autofac. Our controllers are being created by autofac and properly and all required objects are being properly passed in. Those objects usually include services, repositories, and mappers converting domain object to MVC (view) models. So the controller constructor looks somewhat like:

public abcController(
        ILogger logger,
        IabcRepository abcRepository,
        IabcService abcService,
        IMapper<AbcDomain, AbcViewModel> abcMapper,
        ...
        )

Unfortunately, in time, those constructor parameter lists tend to grow quite quickly. Some of our controllers expect now 60 or more parameters.

Did we create some anti-pattern here?

EDIT

I should have mentioned that we try to follow thin contoller pattern. Also most of those parameters tend to be mappers - around 66%. The control methods are usually very simple, and follow either this pattern:

  • Based on parameters call appropriate service or repository
  • Use mapper to convert result to appropriate view model
  • Pass view model to view

Or this pattern:

  • Receive model from post action
  • Use mapper to convert it to appropiate domain object
  • Invoke appropriate service or repository with domain object
like image 437
Sebastian K Avatar asked Nov 30 '22 04:11

Sebastian K


2 Answers

I can't really speak to how you should rearchitect your controller, though I agree with most of the other answers - 60 incoming parameters is a lot.

Something that might help reduce the number of parameters but not the number of dependencies is the Aggregate Service support that Autofac has.

Instead of taking 60 parameters directly, you can take a single aggregate parameter that has 60 properties on it.

You create an interface (just the interface, you don't actually have to implement it) with the dependencies:

public interface IMyAggregateService
{
  IFirstService FirstService { get; }
  ISecondService SecondService { get; }
  IThirdService ThirdService { get; }
  IFourthService FourthService { get; }
}

Then modify your controller to take that aggregate interface:

public class SomeController
{
  private readonly IMyAggregateService _aggregateService;

  public SomeController(
    IMyAggregateService aggregateService)
  {
    _aggregateService = aggregateService;
  }
}

You can register your aggregate service interface, your dependencies, and your controller and when you resolve the controller, the aggregate service interface will automatically be implemented and resolved for you.

var builder = new ContainerBuilder();
builder.RegisterAggregateService<IMyAggregateService>();
builder.Register(/*...*/).As<IFirstService>();
builder.Register(/*...*/).As<ISecondService>();
builder.Register(/*...*/).As<IThirdService>();
builder.Register(/*...*/).As<IFourthService>();
builder.RegisterType<SomeController>();
var container = builder.Build();

Again, it doesn't speak to the larger issue of requiring that many dependencies, but if you are just looking to simplify your constructor and the number of properties on the controller so it's more manageable, this is one strategy Autofac offers to help in that.

Check out the wiki page for more details.

like image 155
Travis Illig Avatar answered Feb 15 '23 03:02

Travis Illig


60 or more parameters is a lot.

In your question you stated "..Those objects usually include services, repositories, and mappers converting domain object to MVC (view) models..."

You've got a Fat Controller (not the Thomas The Task Engine kind) but a controller that is doing too much.

The balance I look for is Fat Model skinny controller. Ian Cooper talks about it well in this blog post

You can also look at things such as which parameters are actually cross cuttings concerns.

For instance Mapping and Logging in my mind are cross cutting concerns so you could potentially use Action Filters to clean up your controllers.

like image 42
heads5150 Avatar answered Feb 15 '23 03:02

heads5150