Unity IoC不会将依赖注入Web API Controller

时间:2015-04-13 17:09:00

标签: c# unity-container asp.net-web-api

我对使用Unity非常陌生,但我的问题是每当我调用我的网络服务时,我都会得到一个例外说明

"确保控制器具有无参数的公共构造函数"

我已经关注了多个教程,但仍然遇到了同样的问题。

在我的WebApiConfig类的Register函数中,我有

var container = new UnityContainer();
container.RegisterType<IValidator, Validator>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);

这是我的UnityResolver类

using Microsoft.Practices.Unity;
using System;
using System.Collections.Generic;
using System.Web.Http.Dependencies;

public class UnityResolver : IDependencyResolver
{
    protected IUnityContainer container;

    public UnityResolver(IUnityContainer container)
    {
        if (container == null)
        {
            throw new ArgumentNullException("container");
        }
        this.container = container;
    }

    public object GetService(Type serviceType)
    {
        try
        {
            return container.Resolve(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return null;
        }
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        try
        {
            return container.ResolveAll(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return new List<object>();
        }
    }

    public IDependencyScope BeginScope()
    {
        var child = container.CreateChildContainer();
        return new UnityResolver(child);
    }

    public void Dispose()
    {
        container.Dispose();
    }
}

我没有注册任何控制器,因为每个教程都声称我不需要这样做。这是我的实际控制器

public class Controller: ApiController
{
    private IValidator _validator;

    public Controller(IValidator validator)
    {
        this._validator = validator;
    }

    [HttpPost]
    public void ReceiveIPN()
    {

    }
}

有没有人对我做错了什么有任何想法?谢谢!

编辑1:这是&#34;实施&#34; Validator类的。这很空,因为在解决Unity问题之前,我并不想在这里引入一个bug。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;


public class Validator: IValidator
{
    public bool ValidateIPN(string body)
    {
        throw new NotImplementedException();
    }
}

编辑2:这是我尝试使用Fiddler调用web api路径时得到的整个错误响应

  

{&#34; message&#34;:&#34;发生错误。&#34;,&#34; exceptionMessage&#34;:&#34;错误   在尝试创建类型为&#39; Controller&#39;的控制器时发生。使   确保控制器具有无参数公共   。构造&#34;&#34; exceptionType&#34;:&#34; System.InvalidOperationException&#34;&#34;堆栈跟踪&#34;:&#34;   在   System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage   请求,HttpControllerDescriptor controllerDescriptor,Type   controllerType)at   System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage   请求)   System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()&#34;&#34;的InnerException&#34; {&#34;消息&#34;:&#34;安   错误已经发生。&#34;,&#34; exceptionMessage&#34;:&#34; Type&#39; Project.Controller&#39;   没有默认值   构造&#34;&#34; exceptionType&#34;:&#34; System.ArgumentException&#34;&#34;堆栈跟踪&#34;:&#34;   在System.Linq.Expressions.Expression.New(Type type)at   System.Web.Http.Internal.TypeActivator.Create [TBASE](类型   instanceType)at   System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage   请求,输入controllerType,Func`1&amp;激活者)   System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage   请求,HttpControllerDescriptor controllerDescriptor,Type   controllerType)&#34;}}

4 个答案:

答案 0 :(得分:26)

所以,经过几个小时的撞墙后,我发现这不起作用,因为我的项目中有一个OWIN / Katana Startup.cs课程。现在我不确切知道这里发生了什么,所以更多信息会很棒。

基本上,由于我使用的是OWIN / Katana,我有一个Startup.cs文件创建了一个新的HttpConfiguration对象并对其进行了配置,类似于它在WebApiConfig.cs类中的完成方式。

private void ConfigureWebApi(HttpConfiguration config)
{
    config.MapHttpAttributeRoutes();
    var container = new UnityContainer();
    container.RegisterType<IValidator, Validator>();
    config.DependencyResolver = new UnityDependencyResolver(container);

    var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter().First();
    jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
}

看起来代码首先通过WebApiConfig的Register函数运行,然后THEN使用Startup.cs文件中生成的对象覆盖HttpConfiguration对象。我不得不在这里移动我的容器设置,以使其工作。

很抱歉,我以前没有提过过OWIN的东西。这对我来说是相当新的,我没有意识到它是相关的。希望这可以为其他人节省我刚刚经历过的痛苦。

答案 1 :(得分:1)

您的Unity容器可能已被处置,因为它仅在WebApiConfig.Register()方法的范围内定义。如果您将容器定义为Global的成员,它将在应用程序的生命周期内保持您的容器,它应该可以工作。

编辑:也不要忘记将容器丢弃在Application_End上。

答案 2 :(得分:0)

  • 通过nuget包在项目中安装Unity.mvc5和Unity.WebApi
  • 按照下面的行指定全名空间

示例:

public static class UnityConfig
{
    public static void RegisterComponents()
    {
        var container = new UnityContainer();

        // register all your components with the container here
        // it is NOT necessary to register your controllers

        // e.g. container.RegisterType<ITestService, TestService>();

        DependencyResolver.SetResolver(new Unity.Mvc5.UnityDependencyResolver(container));

        GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
    }
}

答案 3 :(得分:-1)

我知道这是一篇旧帖子,但由于我遇到了同样的问题,解决方法是简单地将配置对象传递给Unity注册函数并使用该实例中的DependencyResolver:

编辑:刚才注意到接受的答案确实很明显...抱歉垃圾邮件; - )

public static class UnityConfig
{
    public static void Register(HttpConfiguration config)
    {
        var container = new UnityContainer();

        // register your services here...

        // replace...
        /* GlobalConfiguration.Configuration.DependencyResolver = new      Unity.WebApi.UnityDependencyResolver(container); */

        // with this:
        config.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
    }
}