无法使用 Unity 向 ASP.NET Web API 控制器注入依赖项

是否有人成功地使用 IoC 容器将依赖项注入到 ASP.NET WebAPI 控制器中?我似乎不能让它工作。

这就是我现在在做的。

在我的 global.ascx.cs中:

    public static void RegisterRoutes(RouteCollection routes)
{
// code intentionally omitted
}


protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();


RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);


IUnityContainer container = BuildUnityContainer();


System.Web.Http.GlobalConfiguration.Configuration.ServiceResolver.SetResolver(
t =>
{
try
{
return container.Resolve(t);
}
catch (ResolutionFailedException)
{
return null;
}
},
t =>
{
try
{
return container.ResolveAll(t);
}
catch (ResolutionFailedException)
{
return new System.Collections.Generic.List<object>();
}
});


System.Web.Mvc.ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container));


BundleTable.Bundles.RegisterTemplateBundles();
}


private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer().LoadConfiguration();


return container;
}

我的控制器工厂:

public class UnityControllerFactory : DefaultControllerFactory
{
private IUnityContainer _container;


public UnityControllerFactory(IUnityContainer container)
{
_container = container;
}


public override IController CreateController(System.Web.Routing.RequestContext requestContext,
string controllerName)
{
Type controllerType = base.GetControllerType(requestContext, controllerName);


return (IController)_container.Resolve(controllerType);
}
}

它似乎从来没有查看我的统一文件来解决依赖性,我得到了一个错误,如:

试图创建类型为 “ PersonalShopper. Services. WebApi. Controller. ShoppingListController”。 确保控制器具有无参数的公共构造函数。

在 DefaultHttpControllerActivator.Create (HttpControllerContext 控制器上下文,类型控制器类型) 在 System.Web.Http.Dispatcher. DefaultHttpControllerFactory. CreateInstance (HttpControllerContext 控制器上下文,HttpControllerDescriptor 控制器描述器) 在 System.Web.Http.Dispatcher. DefaultHttpControllerFactory. CreateController (HttpControllerContext 控制器上下文,字符串控制器名称) 在 System.Web.Http.Dispatcher. HttpControllerDispatcher. SendAsyncInternal (HttpRequestMessage 请求,取消令牌取消令牌) 在 System.Web.Http.Dispatcher. HttpControllerDispatcher. SendAsync (HttpRequestMessage 请求,取消令牌取消令牌)

控制器看起来像:

public class ShoppingListController : System.Web.Http.ApiController
{
private Repositories.IProductListRepository _ProductListRepository;




public ShoppingListController(Repositories.IUserRepository userRepository,
Repositories.IProductListRepository productListRepository)
{
_ProductListRepository = productListRepository;
}
}

我的联合档案看起来像:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container>
<register type="PersonalShopper.Repositories.IProductListRepository, PersonalShopper.Repositories" mapTo="PersonalShopper.Implementations.MongoRepositories.ProductListRepository, PersonalShopper.Implementations" />
</container>
</unity>

注意,我没有为控制器本身注册,因为在 mvc 的早期版本中,控制器工厂会发现需要解决依赖关系。

我的控制器工厂好像从来没有被调用过。

98420 次浏览

我也抛出了同样的异常,在我的例子中,MVC3和 MVC4二进制文件之间存在冲突。这会阻止我的控制器正确地注册到 IOC 容器中。检查 web.config 并确保它指向正确的 MVC 版本。

我想明白了。

对于 控制器,MVC4使用 System.Web.Http.Dispatcher.IHttpControllerFactorySystem.Web.Http.Dispatcher.IHttpControllerActivator来创建控制器。如果没有静态方法来注册这些实现是什么; 当它们被解析时,mvc 框架在依赖解析器中查找实现,如果没有找到,则使用默认实现。

通过执行以下操作,我得到了控制器依赖关系的统一解析:

创建 UnityHttpControllerActivator:

public class UnityHttpControllerActivator : IHttpControllerActivator
{
private IUnityContainer _container;


public UnityHttpControllerActivator(IUnityContainer container)
{
_container = container;
}


public IHttpController Create(HttpControllerContext controllerContext, Type controllerType)
{
return (IHttpController)_container.Resolve(controllerType);
}
}

将该控制器激活器注册为单元容器本身中的实现:

protected void Application_Start()
{
// code intentionally omitted


IUnityContainer container = BuildUnityContainer();
container.RegisterInstance<IHttpControllerActivator>(new UnityHttpControllerActivator(container));


ServiceResolver.SetResolver(t =>
{
// rest of code is the same as in question above, and is omitted.
});
}

你可能想看看联合酒店。WebApi NuGet 软件包可以解决这些问题,也可以满足 IDisposable 组件的需求。

Http://nuget.org/packages/unity 网络应用程序编程接口

或者

Http://www.devtrends.co.uk/blog/introducing-the-unity.webapi-nuget-package

这里有一个更好的解决方案,它可以正确地工作

Http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver

在最近的 RC 中,我发现不再有 SetResolver 方法。为了同时启用控制器和 webapi 的 IoC,我使用 Unity。WebApi (NuGet)及以下代码:

public static class Bootstrapper
{
public static void Initialise()
{
var container = BuildUnityContainer();


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


ControllerBuilder.Current.SetControllerFactory(new DefaultControllerFactory(new ControllerActivator()));
}


private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();


container.Configure(c => c.Scan(scan =>
{
scan.AssembliesInBaseDirectory();
scan.With<UnityConfiguration.FirstInterfaceConvention>().IgnoreInterfacesOnBaseTypes();
}));


return container;
}
}


public class ControllerActivator : IControllerActivator
{
IController IControllerActivator.Create(RequestContext requestContext, Type controllerType)
{
return GlobalConfiguration.Configuration.DependencyResolver.GetService(controllerType) as IController;
}
}

我也使用 UnityConfiguration (也来自 NuGet)来实现 IoC 魔法。 ;)

在阅读了这些答案之后,我仍然不得不做大量的挖掘工作,才能找到这个问题的答案,因此,为了同行的利益,这里是: 这就是你在 ASP.NET 4 Web API RC 中需要做的全部事情(截止到1913年8月8日) :

  1. 添加对“ Microsoft. Practices. Unity.dll”的引用[ I’m on version 3.0.0.0,通过 NuGet 添加]
  2. 添加对“ Unity. WebApi. dll”的引用[我的版本是0.10.0.0,通过 NuGet 添加的]
  3. 在容器中注册类型映射——类似于通过 Unity 添加到项目中的 Bootstrapper.cs 代码。WebApi 项目。
  4. 在从 ApiController 类继承的控制器中,创建参数化构造函数,将其参数类型作为映射类型

瞧瞧,您得到了注入到构造函数中的依赖项,而不需要另外一行代码!

注意: 我从作者在 这个博客中的一条评论中得到了这个信息。

我在使用联合时也遇到了同样的问题。WebAPI NuGet 包。问题在于,该包从未在 Global.asax 中添加对 UnityConfig.RegisterComponents()的调用。

Global.asax.cs 应该是这样的:

public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
UnityConfig.RegisterComponents();
...
}
}

这个问题发生,由于注册控制器与统一。我通过使用如下所示的按约定注册来解决这个问题。请根据需要过滤掉任何其他类型。

    IUnityContainer container = new UnityContainer();


// Do not register ApiControllers with Unity.
List<Type> typesOtherThanApiControllers
= AllClasses.FromLoadedAssemblies()
.Where(type => (null != type.BaseType)
&& (type.BaseType != typeof (ApiController))).ToList();


container.RegisterTypes(
typesOtherThanApiControllers,
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled);

上面的例子也使用了 AllClasses.FromLoadedAssemblies()。如果您正在从基本路径加载程序集,那么它可能无法在使用 Unity 的 Web API 项目中按预期的方式工作。请看一下我对另一个相关问题的回答。https://stackoverflow.com/a/26624602/1350747

微软已经为此创建了一个包。

从包管理器控制台运行以下命令。

安装软件包 Unity

如果你已经安装了 Unity,它会询问你是否想覆盖 App _ Start UnityConfig.cs。

不需要更改任何其他代码,DI (具有统一性)将工作。

我也犯了同样的错误,花了几个小时在互联网上搜索解决方案。最终,在调用 WebApiConfig 之前,我必须注册 Unity。登记册。我的 Global.asax 现在看起来像

public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
UnityConfig.RegisterComponents();
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}

对我来说,这解决了 Unity 无法解决我的控制器中的依赖性的问题

ASP.NET Web API 2的简短摘要。

从 NuGet 安装 Unity

创建一个名为 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()
{
Dispose(true);
}


protected virtual void Dispose(bool disposing)
{
container.Dispose();
}
}

创建一个名为 UnityConfig的新类:

public static class UnityConfig
{
public static void ConfigureUnity(HttpConfiguration config)
{
var container = new UnityContainer();
container.RegisterType<ISomethingRepository, SomethingRepository>();
config.DependencyResolver = new UnityResolver(container);
}
}

编辑 App _ Start-> WebApiConfig.cs

public static void Register(HttpConfiguration config)
{
UnityConfig.ConfigureUnity(config);
...

现在会成功的。

原始资料,但稍作修改: Https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection