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

查看:26
本文介绍了依赖注入不适用于 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 和依赖项注入.该项目是一个类似于服务的控制台应用程序,这意味着它可以停止和启动.我有一个带有两个构造函数的身份验证控制器:一个无参数,另一个注入存储库.

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 上找到了一些有用的项目,我将它们复制到了 T 恤上,但我遗漏了大部分难题.很有帮助,但没有解决我的问题.我在 Stack Overflow 和 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.

我的代码(细化解释)

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

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

API 控制器

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 集成中的一个常见错误是使用了全局配置.配置.在 OWIN 中,您创建从头开始配置.你不应该参考使用 OWIN 时的 GlobalConfiguration.Configuration整合.

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天全站免登陆