¿Alguien ha tenido éxito al ejecutar un contenedor IoC para inyectar dependencias en los controladores ASP.NET WebAPI? Parece que no puedo hacer que funcione.
Esto es lo que estoy haciendo ahora.
En mi 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;
}
Mi fábrica de controladores:
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);
}
}
Nunca parece buscar en mi archivo de unidad para resolver dependencias, y obtengo un error como:
Se produjo un error al intentar crear un controlador de tipo 'PersonalShopper.Services.WebApi.Controllers.ShoppingListController'. Asegúrese de que el controlador tenga un constructor público sin parámetros.
en System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create (HttpControllerContext controllerContext, Type controllerType) en System.Web.Http.Dispatcher.DefaultHttpControllerFactory.CreateInstance (HttpControllerContext controllerContext, HttpControllerHttpController.Controller, HttpController. (HttpControllerContext controllerContext, String controllerName) en System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncInternal (solicitud HttpRequestMessage, CancellationToken cancellationToken) en System.Web.Http.Dispatcher.HttpControllerDispatlation request, CancellationTokenlation
El controlador se parece a:
public class ShoppingListController : System.Web.Http.ApiController
{
private Repositories.IProductListRepository _ProductListRepository;
public ShoppingListController(Repositories.IUserRepository userRepository,
Repositories.IProductListRepository productListRepository)
{
_ProductListRepository = productListRepository;
}
}
Mi archivo de unidad se ve así:
<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>
Tenga en cuenta que no tengo un registro para el controlador en sí porque en versiones anteriores de mvc, la fábrica de controladores se daría cuenta de que las dependencias debían resolverse.
Parece que nunca se llama a la fábrica de mi controlador.
fuente
GlobalConfiguration.Configuration.ServiceResolver.SetResolver()
?Hay una mejor solución que funciona correctamente aquí.
http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver
fuente
Es posible que desee echar un vistazo al paquete Unity.WebApi NuGet que resolverá todo esto y también atenderá los componentes IDisposable.
ver
http://nuget.org/packages/Unity.WebAPI
o
http://www.devtrends.co.uk/blog/introducing-the-unity.webapi-nuget-package
fuente
UnityResolver
.Microsoft ha creado un paquete para esto.
Ejecute el siguiente comando desde la consola del administrador de paquetes.
paquete de instalación Unity.AspNet.WebApi
Si ya tiene Unity instalado, le preguntará si desea sobrescribir App_Start \ UnityConfig.cs. Responda no y continúe.
No es necesario cambiar ningún otro código y DI (con unidad) funcionará.
fuente
Tuve el mismo error y estuve buscando soluciones en Internet un par de horas. Finalmente, pareció que tenía que registrar Unity ANTES de llamar a WebApiConfig.Register. Mi global.asax ahora parece
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); } }
Para mí, esto resolvió el problema de que Unity no podía resolver las dependencias en mis controladores
fuente
En un RC reciente, descubrí que ya no hay un método SetResolver. Para habilitar IoC para el controlador y webapi, uso Unity.WebApi (NuGet) y el siguiente código:
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; } }
También uso UnityConfiguration (también de NuGet) para la magia de IoC. ;)
fuente
Después de leer las respuestas, todavía tuve que investigar mucho para aterrizar en este problema, así que aquí está para el beneficio de los compañeros: esto es todo lo que necesita hacer en ASP.NET 4 Web API RC (como el 8 de agosto '13):
¡Y he aquí, obtienes las dependencias inyectadas en tu constructor sin otra línea de código!
NOTA: Obtuve esta información de uno de los comentarios en ESTE blog por su autor.
fuente
Breve resumen de ASP.NET Web API 2.
Instalar
Unity
desde NuGet.Crea una nueva clase llamada
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(); } }
Crea una nueva clase llamada
UnityConfig
:public static class UnityConfig { public static void ConfigureUnity(HttpConfiguration config) { var container = new UnityContainer(); container.RegisterType<ISomethingRepository, SomethingRepository>(); config.DependencyResolver = new UnityResolver(container); } }
Editar App_Start -> WebApiConfig.cs
public static void Register(HttpConfiguration config) { UnityConfig.ConfigureUnity(config); ...
Ahora funcionará.
Fuente original pero un poco modificada: https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection
fuente
Tuve la misma excepción y, en mi caso, tuve un conflicto entre los binarios MVC3 y MVC4. Esto impedía que mis controladores se registraran correctamente con mi contenedor IOC. Verifique su web.config y asegúrese de que apunte a las versiones correctas de MVC.
fuente
Este problema ocurre debido al registro de controladores con Unity. Resolví esto usando el registro por convención como se muestra a continuación. Filtre los tipos adicionales según sea necesario.
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);
También el ejemplo anterior usa
AllClasses.FromLoadedAssemblies()
. Si está buscando cargar ensamblados desde la ruta base, es posible que no funcione como se esperaba en un proyecto de API web con Unity. Por favor, eche un vistazo a mi respuesta a otra pregunta relacionada con esto. https://stackoverflow.com/a/26624602/1350747fuente
Tuve el mismo problema al usar el paquete Unity.WebAPI NuGet. El problema fue que el paquete nunca agregó una llamada a
UnityConfig.RegisterComponents()
en mi Global.asax.Global.asax.cs debería verse así:
public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { UnityConfig.RegisterComponents(); ... } }
fuente