2

I'm wiring up Autofac dependency injection within my ASP.NET MVC 5 web application using OWIN middleware (so using startup.cs instead of global.asax), and trying to use property injection to set a public variable within a Controller.

I'm playing around with property injection to have Autofac automatically set the Test property in the LoginController.

public interface ITest
{
    string TestMethod();
}

public class Test : ITest
{
    public string TestMethod()
    {
        return "Hello world!";
    }
}

public class LoginController : Controller
{
    public ITest Test { get; set; }

    public LoginController()
    {
        var aaa = Test.TestMethod();

        // Do other stuff...
    }
}

Here's what my startup.cs looks like. I have been playing around, so some of this code might not be needed (or causing my issue?).

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var builder = new ContainerBuilder();
        builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
        builder.RegisterType<Test>().As<ITest>().SingleInstance();
        builder.Register(c => new Test()).As<ITest>().InstancePerDependency();

        builder.RegisterType<ITest>().PropertiesAutowired();
        builder.RegisterType<LoginController>().PropertiesAutowired();

        builder.RegisterModelBinderProvider();
        builder.RegisterFilterProvider();

        var container = builder.Build();

        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

        app.UseAutofacMiddleware(container);

        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);

        // Some other stuff...
    }
}

So, the 'Test' public property is always null, and therefore breaks on runtime.

Any ideas what could be my issue? Thanks advance for your help! :)

Erik Philips
  • 53,428
  • 11
  • 128
  • 150
  • 2
    Possible duplicate of [How to use Property Injection with AutoFac?](http://stackoverflow.com/questions/15600440/how-to-use-property-injection-with-autofac) – Steve Feb 16 '17 at 23:47
  • I think you have your registrations the wrong way around. The controller needs the `PropertiesAutowired` applied, not the dependency. – Steve Feb 16 '17 at 23:53
  • You either need to pass your Test object into a constructor, or don't use this object within constructor. Properties can't be assigned before the constructor is executed. – trailmax Feb 16 '17 at 23:56
  • @Steve, thanks for that, I will give that a shot. – Dan Gilberstadt Feb 19 '17 at 00:56
  • @trailmax, yea, you're right, properties aren't set until after the constructor has ran. – Dan Gilberstadt Feb 19 '17 at 00:57

1 Answers1

6

So, the 'Test' public property is always null, and therefore breaks on runtime.

It's not always null. It's null in the constructor because Autofac (actually ALL code) cannot set properties until the constructor is finished.

public class LoginController : Controller
{
    public ITest Test { get; set; }

    public LoginController()
    {
        // Test is null, will always be null here
        var aaa = Test.TestMethod();
    }
}

A super dummied down version of autofac does something like:

var controller = new LoginController();
controller.Test = new Test();

If you need to execute code after the property is set you could do something hacky like the following (but really you should just be using constructor injection):

public class LoginController : Controller
{
    private ITest _test;
    public ITest Test 
    { 
      get { return _test; }
      set 
      {
        var initialize = (_test == null);
        _test = value;
        if (initialize)
        {
          Initialize();
        }
      }
    }

    public LoginController()
    {
    }

    private void Initialize()
    {
      var aaa = Test.TestMethod();
    }
}

Again the more logical way would be to just do:

public class LoginController : Controller
{
    private readonly ITest _test;

    public LoginController(ITest test)
    {
        _test = test;
        var aaa = _test.TestMethod();

        // Do other stuff...
    }
}
Erik Philips
  • 53,428
  • 11
  • 128
  • 150
  • Ahh, thanks Erik! Didn't realize that the Test would be set AFTER the constructor finished. I see this working now. I think I should be go to go. Thank you! – Dan Gilberstadt Feb 17 '17 at 00:11