2

I have two projects: a standard Web Api project and a class library project which contains all the controllers. In the Web Api I have the following on the Global.asax class:

public class MvcApplication : HttpApplication
{
    protected void Application_Start()
    {
        WebApiConfig.Register(GlobalConfiguration.Configuration);

        RouteConfig.RegisterRoutes(RouteTable.Routes);

        var builder = new ContainerBuilder();

        builder.RegisterApiControllers(GetAssemblies(true)).PropertiesAutowired();
        builder
            .RegisterAssemblyTypes(GetAssemblies(false))             
            .Where(t => t.GetCustomAttributes(typeof(IocContainerMarkerAttribute), false).Any())
            .PropertiesAutowired();

        GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(builder.Build());
    }

    private static Assembly[] GetAssemblies(bool isController)
    {
        var path = HttpContext.Current.Server.MapPath("~/Bin");

        return isController
            ? Directory.GetFiles(path, "*.dll") .Where(x => x.Contains(".Controllers")).Select(Assembly.LoadFile).ToArray()
            : Directory.GetFiles(path, "*.dll").Select(Assembly.LoadFile).ToArray();
    }
}

the controller:

public class PropertyAgentController : ApiController
{
    public ICommandControllerProcessor CommandControllerProcessor { get; set; }


    [HttpPost]
    public HttpResponseMessage HandleMessage()
    {
        return CommandControllerProcessor.HandleMessage(this);
    }
}

and the dependency:

public interface ICommandControllerProcessor
{
    HttpResponseMessage HandleMessage(ApiController controller);
}

[IocContainerMarker]
public class CommandControllerProcessor : ICommandControllerProcessor
{
    public virtual HttpResponseMessage HandleMessage(ApiController controller)
    {
        return null;
    }
}

The CommandControllerProcessor class lives in the web api project. The property was being resolved when I had the controllers in the same project but as soon as I created a different project, the controllers are still discovered but the property is not wired.

Any ideas of what the problem might be?

Thanks a lot.

MeTitus
  • 3,390
  • 2
  • 25
  • 49
  • Do you reference or using types directly in your web.api project from the class library project? Or do you only dynamically loading your `.Controller` assemblies when configuring autofac? – nemesv Jan 03 '14 at 11:44
  • Everything is loaded dynamically with Autofac, and there aren't any direct references between the project. Thanks – MeTitus Jan 03 '14 at 11:56
  • 1
    Try to replace the `Assembly.LoadFile` in your `GetAssemblies` method with `Assembly.LoadFrom`. You can read about the differences here: http://stackoverflow.com/questions/1477843/difference-between-loadfile-and-loadfrom-with-net-assemblies – nemesv Jan 03 '14 at 12:05
  • It did not make any difference. I can see the types registered in Autofac, but I still gave a try as somthing odd could be happen, but it does fix the problem. I can see the implementation type on the list or registrations... it seems that in this particular case the method PropertiesAutowired is not working as it should. – MeTitus Jan 03 '14 at 12:12
  • 1
    Ok, it seems you are overriding your registrations. When you call `GetAssemblies(false)` it is again reloads your `.Controllers` so change your assembly loading code to: `return isController ? Directory.GetFiles(path, "*.dll").Where(x => x.Contains(".Controllers")).Select(Assembly.LoadFile).ToArray() : Directory.GetFiles(path, "*.dll").Where(x => !x.Contains(".Controllers")).Select(Assembly.LoadFile).ToArray();` note the nagation `!` in the second `Where`. – nemesv Jan 03 '14 at 12:54
  • Thanks nemesv for the hints... I completely forgot about the registration overriding. I also had an issue with the LoadFromFile method a while ago but completely missed it as well. Thanks a lot :) – MeTitus Jan 03 '14 at 13:23
  • @nemesv one thing I never understood why was the registrations were being overwritten - I am calling RegisterApiControllers only once and I have a filter when using RegisterAssemblyTypes, so why would this override any previous registrations. I am having the same issue in a sightly different setup, thanks :) – MeTitus Jan 29 '18 at 16:09

1 Answers1

3

I followed the hints nemesv gave me and got it working. It was basically a couple of things missing but the registration overriding and the usage of LoadFile were definitely a problem.

    protected void Application_Start()
    {
        WebApiConfig.Register(GlobalConfiguration.Configuration);

        RouteConfig.RegisterRoutes(RouteTable.Routes);

        var builder = new ContainerBuilder();

        builder.RegisterApiControllers(GetAssemblies(true)).PropertiesAutowired();

        builder
            .RegisterAssemblyTypes(GetAssemblies(false))             
            .Where(t => t.GetCustomAttributes(typeof(IocContainerMarkerAttribute), false).Any())
            .AsImplementedInterfaces()
            .PropertiesAutowired();

        GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(builder.Build());
    }

    private static Assembly[] GetAssemblies(bool isController)
    {
        var path = HttpContext.Current.Server.MapPath("~/Bin");

        return isController
            ? Directory.GetFiles(path, "*.dll").Where(x => x.Contains(".Controllers")).Select(Assembly.LoadFrom).ToArray()
            : Directory.GetFiles(path, "*.dll").Where(x => !x.Contains(".Controllers")).Select(Assembly.LoadFrom).ToArray();
    }
MeTitus
  • 3,390
  • 2
  • 25
  • 49