Impossible d’injecter des dépendances dans le contrôleur API Web ASP.NET à l’aide d’Unity

Quelqu’un at-il réussi à utiliser un conteneur IoC pour injecter des dépendances dans les contrôleurs ASP.NET WebAPI? Je n’arrive pas à le faire fonctionner.

C’est ce que je fais maintenant.

Dans mon 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(); } }); System.Web.Mvc.ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container)); BundleTable.Bundles.RegisterTemplateBundles(); } private static IUnityContainer BuildUnityContainer() { var container = new UnityContainer().LoadConfiguration(); return container; } 

Mon usine de contrôleur:

 public class UnityControllerFactory : DefaultControllerFactory { private IUnityContainer _container; public UnityControllerFactory(IUnityContainer container) { _container = container; } public override IController CreateController(System.Web.Routing.RequestContext requestContext, ssortingng controllerName) { Type controllerType = base.GetControllerType(requestContext, controllerName); return (IController)_container.Resolve(controllerType); } } 

Il ne semble jamais regarder dans mon fichier d’unité pour résoudre les dépendances, et j’ai une erreur comme:

Une erreur s’est produite lors de la tentative de création d’un contrôleur de type ‘PersonalShopper.Services.WebApi.Controllers.ShoppingListController’. Assurez-vous que le contrôleur dispose d’un constructeur public sans paramètre.

at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create (HttpControllerContext controllerContext, Type controllerType) à System.Web.Http.Dispatcher.DefaultHttpControllerFactory.CreateInstance (HttpControllerContext controllerContext, HttpControllerDescriptor controllerDescriptor) à System.Web.Http.Dispatcher.DefaultHttpControllerFactory.CreateController (HttpControllerContext controllerContext, Ssortingng controllerName) à System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncInternal (demande HttpRequestMessage, CancellationToken cancelToken) à System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync (demande HttpRequestMessage, annulationToken AnnulationToken)

Le contrôleur ressemble à:

 public class ShoppingListController : System.Web.Http.ApiController { private Repositories.IProductListRepository _ProductListRepository; public ShoppingListController(Repositories.IUserRepository userRepository, Repositories.IProductListRepository productListRepository) { _ProductListRepository = productListRepository; } } 

Mon fichier d’unité ressemble à:

      

Notez que je n’ai pas d’inscription pour le contrôleur lui-même, car dans les versions précédentes de mvc, la fabrique de contrôleurs estimait que les dépendances devaient être résolues.

Il semble que ma fabrique de contrôleurs ne soit jamais appelée.

    Deviner.

    Pour ApiControllers , MVC 4 utilise System.Web.Http.Dispatcher.IHttpControllerFactory et System.Web.Http.Dispatcher.IHttpControllerActivator pour créer les contrôleurs. S’il n’y a pas de méthode statique pour enregistrer ce que sont ces implémentations; lorsqu’elles sont résolues, le framework mvc recherche les implémentations dans le résolveur de dépendances et, si elles ne sont pas trouvées, utilise les implémentations par défaut.

    J’ai obtenu la résolution d’unité des dépendances de contrôleur en procédant comme suit:

    Création d’un 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); } } 

    Enregistré cet activateur de contrôleur comme l’implémentation dans le conteneur d’unité lui-même:

     protected void Application_Start() { // code intentionally omitted IUnityContainer container = BuildUnityContainer(); container.RegisterInstance(new UnityHttpControllerActivator(container)); ServiceResolver.SetResolver(t => { // rest of code is the same as in question above, and is omitted. }); } 

    Il y a une meilleure solution qui fonctionne correctement ici

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

    Vous voudrez peut-être jeter un coup d’œil au package Unity.WebApi NuGet qui va tout régler et qui prendra également en charge les composants IDisposables.

    voir

    http://nuget.org/packages/Unity.WebAPI

    ou

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

    Microsoft a créé un package pour cela.

    Exécutez la commande suivante à partir de la console du gestionnaire de packages.

    package d’installation Unity.AspNet.WebApi

    Si vous avez déjà installé Unity, il vous demandera si vous souhaitez remplacer App_Start \ UnityConfig.cs. Répondez non et continuez.

    Pas besoin de changer un autre code et DI (avec unité) fonctionnera.

    J’ai eu la même erreur et cherchais sur Internet quelques heures. Finalement, il est apparu que je devais enregistrer Unity AVANT d’appeler le WebApiConfig.Register. Mon global.asax ressemble maintenant à

     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); } } 

    Pour moi, cela a résolu le problème que Unity ne pouvait pas résoudre les dépendances dans mes contrôleurs

    Dans un récent RC, je trouve qu’il n’y a plus de méthode SetResolver. Pour activer à la fois IoC pour le contrôleur et webapi, j’utilise Unity.WebApi (NuGet) et le code suivant:

     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().IgnoreInterfacesOnBaseTypes(); })); return container; } } public class ControllerActivator : IControllerActivator { IController IControllerActivator.Create(RequestContext requestContext, Type controllerType) { return GlobalConfiguration.Configuration.DependencyResolver.GetService(controllerType) as IController; } } 

    J’utilise aussi UnityConfiguration (également de NuGet) pour la magie IoC. 😉

    Après avoir lu les réponses, je devais encore faire beaucoup de recherches pour obtenir ce piège, donc la voici pour le bénéfice des pairs: c’est tout ce que vous devez faire dans ASP.NET 4 Web API RC (comme le 8 août). ’13):

    1. Ajoutez une référence à “Microsoft.Practices.Unity.dll” [Je suis sur la version 3.0.0.0, ajoutée via NuGet]
    2. Ajoutez une référence à “Unity.WebApi.dll” [Je suis sur la version 0.10.0.0, ajoutée via NuGet]
    3. Enregistrez vos mappages de type avec le conteneur – similaire au code dans Bootstrapper.cs qui est ajouté à votre projet par le projet Unity.WebApi.
    4. Dans les contrôleurs qui héritent de la classe ApiController, créez des constructeurs paramétrés ayant leurs types de parameters en tant que types mappés

    Et voilà, vous obtenez les dépendances injectées dans votre constructeur sans autre ligne de code!

    NOTE: J’ai eu cette information d’un des commentaires dans ce blog par son auteur.