views:

1096

answers:

4

Hi,

My question is as follows: I have a base controller (ASP.Net MVC controller) called ApplicationController, and I want all my controller to inherit from it. this base controller has a ILogger property, marked with a [Dependency] attribute. (yes, I know I should use constructor injection, I'm just curious about this attribute).

I created the container, registered types, changed the default factory, everything is fine. the problem is that when I try to use my Logger property in the derived controller, it's not resolved.

what am I doing wrong? why doesn't the container resolves the base class dependencies when creating the derived controller?

code samples:


ApplicationController:

public class ApplicationController : Controller
{
    [Dependency]
    protected ILogger _logger { get; set; }

}

derived controller:

public class HomeController : ApplicationController
{
    public HomeController()
    {

    }
    public ActionResult Index()
    {
        _logger.Log("Home controller constructor started.");
        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        return View();
    }

    public ActionResult About()
    {
        return View();
    }
}

Unity controller factory:

public class UnityControllerFactory : DefaultControllerFactory
{
    private readonly IUnityContainer _container;
    public UnityControllerFactory(IUnityContainer container)
    {
        _container = container;
    }

    protected override IController GetControllerInstance(Type controllerType)
    {
        return _container.Resolve(controllerType) as IController;
    }
}

Global.asax.cs sample:

protected void Application_Start()
    {
        _container = new UnityContainer();
        _container.RegisterType<ILogger, Logger.Logger>();
        UnityControllerFactory factory = new UnityControllerFactory(_container);
        ControllerBuilder.Current.SetControllerFactory(factory);

        RegisterRoutes(RouteTable.Routes);
    }


I'm quite new to Unity, so maybe I did something wrong.

thanks, Ami.

A: 

I'm not sure if this is related, but usually, I avoid having namespaces and classes with the same name (in your case, Logger.Logger), for I had problems with this in the past. But that may be not the problem.

I'm also not sure if the [Dependency] attribute works for derived types. If you change it for constructor injection, does this still not work? Something like:

public class ApplicationController : Controller
{
    protected ILogger _logger { get; set; }


    public ApplicationController(ILogger logger)
    {
         this._logger = logger;

    }
}

and

public class HomeController : ApplicationController
{
 public HomeController(ILogger logger) : base(logger)
 {

 }
 public ActionResult Index()
 {
  _logger.Log("Home controller constructor started.");
  ViewData["Message"] = "Welcome to ASP.NET MVC!";

  return View();
 }

 public ActionResult About()
 {
  return View();
 }
}

and the rest just the same. The code looks ok.

Samuel Carrijo
A: 

I'm fairly unexperienced with unity as well, but I think you need to register your HomeController with the contsaner, not the logger.

Adam Barney
It is correct to register the logger because you want to inject your dependency (an ILogger implementation).
Jakob Christensen
+4  A: 

AFAIK, Unity will only resolve public properties. Therefore your protected property will not be resolved.

Jakob Christensen
OK, Jakob gets 2 points :)changing the property to public solved the problem. the Unity container resolved the dependency and all is well.
Ami
A: 

I had the same issue, and fixed it by changing the ILogger to public. This is with an ASP.NET MVC2 project in VS2010, .NET 4. It makes sense, logically, since Unity isn't creating a proxy class or anything, it's just setting properties that it has access to, and has a mapping for - hence public only.

Douglas R