L’iniezione delle dipendenze non funziona con Web Api 2 e Autofac ospitati da Owin

Sto trovando i miei piedi con Web Api 2, Owin e Autofac e ho bisogno di una guida, per favore.

Panoramica
Ho un web API Owin self-hosted che utilizza Autofac per IoC e l’iniezione delle dipendenze. Il progetto è un’app console che funziona come un servizio, il che significa che può essere arrestato e avviato. Ho un controller di autenticazione con due costruttori: un parametro-less e l’altro inietta un repository.

Problema
Quando eseguo il servizio e chiamo l’API, viene chiamato il mio costruttore senza parametri e il mio repository non viene mai iniettato (_repository = null).

Ricerca
Ho fatto un bel po ‘di ricerche e ho trovato alcuni progetti utili su Github, che ho replicato al tee, ma mi manca una grande parte del puzzle. Questo è stato utile ma non ha risolto il mio problema. Ho letto questa domanda su Stack Overflow e Dane Sparza ha avuto un bel progetto demo ma non sono riuscito a trovare una soluzione chiara. Il problema non è l’auto-hosting, ma l’iniezione di dipendenza.

Il mio codice (assottigliato per la spiegazione)

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().InstancePerRequest(); // Register a logger service to be used by the controller and middleware. builder.RegisterType().As().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. } 

Program.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(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); } } 

Dovresti utilizzare HttpConfiguration con cui stai eseguendo il bootstrap di OWIN ovunque. Così questo:

 GlobalConfiguration.Configuration.DependencyResolver = resolver; 

Dovrebbe diventare:

 config.DependencyResolver = resolver; 

Oltre a questo, tutto sembra a posto. I controller Api sono registrati, anche se non gli stai dando un ambito. Non sono sicuro se in ambito Autofac le impostazioni predefinite siano per richiesta per i controllori o se abbia la nozione di ambito per-richiesta (so che LightInject ce l’ha).

Guardandomi intorno, penso che tu abbia seguito l’esempio sul repository di Google Code per Autofac, che utilizza effettivamente GlobalConfiguration. Invece, se si guarda all’esempio di GitHub , è un po ‘diverso. Prova a fare le modifiche in base a questo. Compreso questo:

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

Aggiornamento 2016

Quello che ho detto sopra vale ancora, ma qualcosa in più dai documenti di Autofac (grazie Brad):

Un errore comune nell’integrazione OWIN è l’uso di GlobalConfiguration.Configuration. In OWIN si crea la configurazione da zero. Non si dovrebbe fare riferimento a GlobalConfiguration.Configuration in qualsiasi momento quando si utilizza l’integrazione OWIN.