依赖项注入不适用于Owin自托管的Web Api 2和Autofac [英] Dependency injection not working with Owin self-hosted Web Api 2 and Autofac

查看:79
本文介绍了依赖项注入不适用于Owin自托管的Web Api 2和Autofac的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Web Api 2,Owin和Autofac站起来,请提供一些指导.

I'm finding my feet with Web Api 2, Owin and Autofac and need some guidance, please.

概述
我有一个Owin自托管Web Api,它使用Autofac进行IoC和依赖注入.该项目是一个充当服务的控制台应用程序,这意味着它可以停止和启动.我有一个带有两个构造函数的Authentication控制器:一个没有参数,另一个则注入一个存储库.

Overview
I have an Owin self-hosted Web Api that uses Autofac for IoC and dependency injection. The project is a console app acting like a service, meaning it can be stopped and started. I have an Authentication controller with two constructors: one parameter-less and the other injects a repository.

问题
当我运行该服务并调用api时,将调用我的无参数构造函数,并且永远不会注入我的存储库(_repository = null).

Problem
When I run the service and call the api, my parameter-less constructor is called and my repository never gets injected (_repository = null).

研究
我已经做了相当多的研究,并在Github上找到了一些有用的项目,这些项目已经复制到了发球台上,但是我却错过了很大一部分难题. 很有帮助,但没有解决我的问题.我在堆栈溢出和Dane Sparza上阅读了这个问题有一个很好的演示项目,但我找不到明确的解决方案.问题不在于自托管,而是依赖注入.

Research
I've done a fair bit of research and found some helpful projects on Github, which I replicated to the tee but I'm missing a big part of the puzzle. This was helpful but didn't solve my problem. I read this question on Stack Overflow and Dane Sparza had a nice demo project but I couldn't find a clear solution. The problem is not the self-hosting but the dependency injection.

我的代码(为便于解释,请细化)

My code (thinned out for explanation)

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.
    }

Program.cs

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<Startup>(url: baseAddress);
           },
           delegate()
           {
               if (_server != null)
               {
                   _server.Dispose();
               }
           }
       );
    }

ApiController

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);
    }
}

推荐答案

您应该使用HttpConfiguration引导OWIN. 所以,这个:

You should be using the HttpConfiguration with which you're bootstrapping OWIN everywhere. So, this:

GlobalConfiguration.Configuration.DependencyResolver = resolver;

应成为:

config.DependencyResolver = resolver;

除此之外,一切看起来都不错. Api控制器已注册,尽管您没有给它们指定范围.不知道在Autofac中,作用域范围默认为对控制器的按请求作用域,还是根本没有按请求作用域的概念(我知道LightInject就是这样).

Other than that, everything looks good. Api controllers are registered, although you're not giving them a scope. Not sure if in Autofac scoping defaults to per-request for controllers or if it has the notion of per-request scoping at all (I know that LightInject has it).

环顾四周,我认为您遵循了Autofac的Google代码存储库中的示例,该示例确实使用了GlobalConfiguration.相反,如果您查看 GitHub示例 ,这有点不同.尝试根据此进行更改.包括这个:

Looking around, I think you followed the example on the Google Code repo for Autofac, which indeed uses GlobalConfiguration. Instead, if you look at the GitHub example, it is a bit different. Try to make the changes according to this. Including this:

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


2016年更新

我上面所说的内容仍然适用,但是Autofac的文档有一些其他优点(感谢Brad):

What I said above still applies, but something extra from Autofac's docs (thanks Brad):

OWIN集成中的一个常见错误是使用 GlobalConfiguration.Configuration.在OWIN中,您可以创建 从头开始配置.你不应该参考 GlobalConfiguration.Configuration在使用OWIN的任何地方 整合.

A common error in OWIN integration is use of the GlobalConfiguration.Configuration. In OWIN you create the configuration from scratch. You should not reference GlobalConfiguration.Configuration anywhere when using the OWIN integration.

这篇关于依赖项注入不适用于Owin自托管的Web Api 2和Autofac的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆