La inyección de dependencias no funciona con la Api Web auto-alojada de Owin 2 y Autofac


Estoy encontrando mis pies con Web Api 2, Owin y Autofac y necesito un poco de orientación, por favor.

Descripción general
Tengo una Api Web autohospedada de Owin que utiliza Autofac para IoC e inyección de dependencias. El proyecto es una aplicación de consola que actúa como un servicio, lo que significa que se puede detener e iniciar. Tengo un controlador de autenticación con dos constructores: uno sin parámetros y el otro inyecta un repositorio.

Problema
Cuando corro el servicio y llamo a la api, se llama a mi constructor sin parámetros y mi repositorio nunca se inyecta (_repository = null).

Investigación
He hecho un poco de investigación y encontré algunos proyectos útiles en Github, que replicé al tee, pero me estoy perdiendo una gran parte del rompecabezas. Esto fue útil pero no resolvió mi problema. Leí esta pregunta en Stack Overflow y Dane Sparza tenía un buen proyecto de demostración pero no pude encontrar una solución clara. El problema es no el auto-alojamiento, sino la inyección de dependencia.

Mi código (diluido para explicación)

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        HttpConfiguration config = new HttpConfiguration();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        var json = config.Formatters.JsonFormatter;
        json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
        config.Formatters.Remove(config.Formatters.XmlFormatter);

        var connectioninfo = ConnectionInfo.FromAppConfig("mongodb");

        var builder = new ContainerBuilder();                                    // Create the container builder.
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly());         // Register the Web API controllers.
        builder.Register(c => new Logger()).As<ILogger>().InstancePerRequest();  // Register a logger service to be used by the controller and middleware.
        builder.RegisterType<AuthenticationRepository>().As<IAuthenticationRepository>().WithParameter(new NamedParameter("connectionInfo", connectioninfo)).InstancePerRequest();

        var container = builder.Build();

        var resolver = new AutofacWebApiDependencyResolver(container);           // Create an assign a dependency resolver for Web API to use.
        GlobalConfiguration.Configuration.DependencyResolver = resolver;         // Configure Web API with the dependency resolver

        app.UseCors(CorsOptions.AllowAll);  
        app.UseWebApi(config);
        app.UseAutofacWebApi(config);  // Make sure the Autofac lifetime scope is passed to Web API.
    }

Programa.cs

 static void Main(string[] args)
    {           
        var service = new ApiService(typeof(Program), args);

        var baseAddress = "http://localhost:9000/";
        IDisposable _server = null;

        service.Run(
           delegate()
           {
               _server = WebApp.Start<Startup>(url: baseAddress);
           },
           delegate()
           {
               if (_server != null)
               {
                   _server.Dispose();
               }
           }
       );
    }

ApiController

public class AuthenticationController : ApiController
{
    private IAuthenticationRepository _repository;

    public AuthenticationController() { }

    public AuthenticationController(IAuthenticationRepository repository)
    {
        _repository = repository;
    }

    [AllowAnonymous]
    public IHttpActionResult Authenticate(string name, string password)
    {
        if (_repository == null)
            return BadRequest("User repository is null.");

        var valid = _repository.AuthenticateUser(name, password);
        return Ok(valid);
    }
}
Author: Community, 2014-08-07

1 answers

Deberías usar el HttpConfiguration con el que estás bootstrapeando a OWIN en todas partes. Entonces, esto:

GlobalConfiguration.Configuration.DependencyResolver = resolver;

Debe convertirse en:

config.DependencyResolver = resolver;

Aparte de eso, todo se ve bien. Los controladores de api están registrados, aunque no les está dando un alcance. No estoy seguro de si en Autofac el alcance predeterminado es por solicitud para los controladores o si tiene la noción de alcance por solicitud (sé que LightInject lo tiene).

Mirando a su alrededor, creo que siguió el ejemplo en el Código de Google repo para Autofac, que de hecho utiliza GlobalConfiguration. En cambio, si nos fijamos en el ejemplo de GitHub , es un poco diferente. Trate de hacer los cambios de acuerdo a esto. Incluyendo esto:

// This should be the first middleware added to the IAppBuilder.
app.UseAutofacMiddleware(container);

2016 actualización

Lo que dije anteriormente todavía se aplica, pero algo extra de los documentos de Autofac (gracias Brad):

Un error común en la integración de OWIN es el uso de la Configuración global.Configuración. En OWIN se crea la configuración desde cero. Usted no debe hacer referencia Configuración global.Configuración en cualquier lugar cuando se utiliza el OWIN integración.

 36
Author: Marcel N.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-06 08:55:21