使用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); } }
它似乎从来没有看我的统一文件来解决依赖,我得到一个错误,如:
尝试创buildtypes为“PersonalShopper.Services.WebApi.Controllers.ShoppingListController”的控制器时发生错误。 确保控制器有一个无参数的公共构造函数。
在System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpControllerContext controllerContext,typescontrollerType)在System.Web.Http.Dispatcher.DefaultHttpControllerFactory.CreateInstance(HttpControllerContext controllerContext,HttpControllerDescriptor controllerDescriptor)在System.Web.Http.Dispatcher.DefaultHttpControllerFactory.CreateController (HttpControllerContext controllerContext,string控制器名称)在System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(HttpRequestMessage请求,CancellationToken的cancellationToken)System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncInternal(HttpRequestMessage请求,CancellationToken的cancellationToken)
控制器看起来像:
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版本中,控制器工厂会发现需要解决依赖关系。
看来我的控制器工厂从来没有被称为。
弄清楚了。
对于ApiControllers ,MVC 4使用System.Web.Http.Dispatcher.IHttpControllerFactory和System.Web.Http.Dispatcher.IHttpControllerActivator来创build控制器。 如果没有静态方法来注册它们的实现, 当它们被parsing时,mvc框架会在依赖parsing器中查找实现,如果找不到,则使用默认实现。
我通过执行以下操作来实现控制器依赖关系的统一parsing:
创build一个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. }); }
有一个更好的解决scheme,在这里正确工作
http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver
你可能想看一看Unity.WebApi NuGet包,它将把所有这些都sorting出来,并且还会处理IDisposable组件。
看到
http://nuget.org/packages/Unity.WebAPI
要么
http://www.devtrends.co.uk/blog/introducing-the-unity.webapi-nuget-package
微软已经为此创build了一个包。
从包pipe理器控制台运行以下命令。
安装包Unity.AspNet.WebApi
如果你已经安装了Unity,它会询问你是否要覆盖App_Start \ UnityConfig.cs。 答复否,然后继续。
没有必要改变任何其他代码和DI(与统一)将工作。
我有同样的错误,并正在寻找互联网解决scheme几个小时。 最终,在我调用WebApiConfig.Register之前,我必须注册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无法解决我的控制器中的依赖问题
在最近的RC中,我发现不再有SetResolver方法。 为了启用IoC for controller和webapi,我使用了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中这是你需要做的(8月8日'13):
- 添加对“Microsoft.Practices.Unity.dll”的引用[我在版本3.0.0.0,通过NuGet添加]
- 添加对“Unity.WebApi.dll”的引用[我在版本0.10.0.0,通过NuGet添加]
- 在容器中注册types映射 – 类似于通过Unity.WebApi项目添加到项目中的Bootstrapper.cs中的代码。
- 在从ApiController类inheritance的控制器中,创build具有作为映射types的参数types的参数化构造函数
瞧,你会得到注入你的构造函数没有另一行代码的依赖关系!
注意:我从本文的作者的评论中获得了这些信息。
我有同样的exception被抛出,在我的情况下,我有一个MVC3和MVC4二进制文件之间的冲突。 这阻止了我的控制器在我的IOC容器中正确注册。 检查你的web.config,并确保它指向正确的MVC版本。
由于注册与Unity的控制器发生此问题。 我通过按照惯例使用注册来解决这个问题,如下所示。 请根据需要筛选出其他types。
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()
。 如果您正在从基本path加载程序集,则可能无法按预期在使用Unity的Web API项目中正常工作。 请看看我对这个问题的回答。 https://stackoverflow.com/a/26624602/1350747
使用Unity.WebAPI NuGet包时遇到同样的问题。 问题是该包从未在我的Global.asax中添加对UnityConfig.RegisterComponents()
的调用。
Global.asax.cs应该如下所示:
public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { UnityConfig.RegisterComponents(); ... } }
ASP.NET Web API 2的简短摘要
从NuGet安装Unity
。
创build一个名为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(); } }
创build一个名为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 : //docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection