1

I have a project setup with UnitOfWork Interfaces and Managers. All this works well while I just had to use an accountMananger for the base of my controller.

    protected BaseController(IAccountManager acctManager)
    {
        _accountManager = acctManager;
    }

and my controllers are created like this, and works.

  public class AccountController : BaseController
  {
    public AccountController(IAccountManager accountManager)
        : base(accountManager)
    {
    }

Now I am creating other business managers and I realise that by the end of the project my BaseController constructor is going to be huge or I am going to have a load of various signatures based on the controller I am on. And if I forgot something and needed another manager and changes one constructor, all the other controllers need to also change.

I mean, I actually ALWAYS want accountManager to be injected/resolved in the base. Can I do that? Since I am 99% checking for authorisation.

I have read about ControllerFactories but also somebody mentioned to implement IDependancyResolver , but no example, which is his preferred way to do it.

I can see this becoming a big burden to create constructors based on the controllers I need, which I dont have yet.

Can any body give me an example of how to easily access my managers in the base, as I need them. I mean, they all created and ready to be resolved anyway.. so why the heck do I need to pass them in such a strange way anyway?

Sorry. Just learning about DI and this is from a good tutorial but as you can see lacking some further explanation.

1 Answer 1

2

What you have with your account manager is called a Cross-Cutting Concern. There are a few different ways to skin this cat, but you should avoid injecting the same dependency into every controller.

In general, it is also better to avoid inheritance because that will cause tight coupling between your classes. The tight coupling is obvious here - what if you needed a controller that didn't have IAccountManager as a dependency later?

In this particular case, there is already a built-in loosely coupled authorization framework in MVC that you can utilize - the AuthorizeAttribute, which is the normal way of handling access to your controller action methods.

[Authorize] 
public class AccountController : Controller
{
    public AccountController () { . . . }

    [AllowAnonymous]
    public ActionResult Register() { . . . }

    public ActionResult Manage() { . . . }

    public ActionResult LogOff() { . . . }
} 

There are also several other options for implementing cross-cutting concerns - implementing IActionFilter - see this for a DI friendly example, interception (which some DI containers support), using the Decorator Pattern, and putting the dependencies in ambient context (such as HttpContext.Items).

I can see this becoming a big burden to create constructors based on the controllers I need, which I dont have yet.

This is why you should inherit DefaultControllerFactory and provide it with the one instance of your DI container at application startup (in the composition root). It is typically the container's responsibility to provide the dependencies to your controllers, especially if your application is large.

public class AutofacControllerFactory
    : DefaultControllerFactory
{
    private readonly IContainer container;

    public InjectableControllerFactory(IContainer container)
    {
        if (container == null)
            throw new ArgumentNullException("container");
        this.container = container;
    }

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (requestContext.HttpContext.Request.Url.ToString().EndsWith("favicon.ico"))
            return null;

        return controllerType == null ?
            base.GetControllerInstance(requestContext, controllerType) :
            this.container.Resolve(controllerType) as IController;
    }
}

I strongly recommend you read the book Dependency Injection in .NET. DI is one of the most misunderstood concepts in software development, and it is well worth the investment of studying the topic in detail on its own without having to sift through the misinformation on the Internet. There are many benefits to be gained by proper use of DI, but improper usage is often worse than not using DI at all.

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks for providing some nice info. We already use the Authorize attribute but out base controller override the OnAuthroizing to do some checks, set up session, requiring accountManager to call the accountRepo on every call to update various things. But as you suggest controllerFacotry, which seems to be suggested 9/10 times, I most likley need to work out how to do that. I am struggling to find the real benefit of using DI but I really want to understand what it is really all about. Thanks +1
LOL- I think I am classic example of AN ABSTRACT FACTORY ON STEROID :) Unlearned...
Well, the Authorize Attribute can be inherited to do just that, although, for DI purposes it would be better to separate it into an IAuthorizationFilter and an attribute with no behavior similar to what is shown here. It is also a best practice to separate each concern into a separate service - (update various things, do some checks). The fact that it is named AccountManager is a code smell that indicates it is doing more than one thing (which is bad).
Yea now I am beginning to think that DI was no necessary in this project at all. Its well defined and its almost certain the web layer wont change. We can already swap out repositories or implementation of DB.. so why go to the trouble of DI in the MVC app. Got UnitOfWork and business loosely coupled and to test-doubles can be used later with DI. It might have just been that we use DI here because... well everybody talking about it. If I understood the first chapter correctly then there is no need for DI here.
Well, there is a difference between not using DI and not using a DI container. You can use the DI pattern just fine with no container. But that doesn't mean you shouldn't follow the practice of using constructor injection. Testability is only one benefit of DI. One of the primary benefits is being able to extend the software easily without changing it (not just swap implementations, but that is a benefit, too).
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.