Czy ktoś odniósł jakikolwiek sukces, używając kontenera IoC do wstrzykiwania zależności do kontrolerów ASP.NET WebAPI? Nie wydaje mi się, żeby to działało.
To właśnie teraz robię.
W moim 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;
}
Moja fabryka kontrolerów:
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);
}
}
Wydaje się, że nigdy nie zagląda do mojego pliku unity, aby rozwiązać zależności, i otrzymuję błąd taki jak:
Wystąpił błąd podczas próby utworzenia kontrolera typu „PersonalShopper.Services.WebApi.Controllers.ShoppingListController”. Upewnij się, że kontroler ma konstruktora publicznego bez parametrów.
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create (HttpControllerContext controllerContext, Type controllerType) w System.Web.Http.Dispatcher.DefaultHttpControllerFactory.CreateInstance (HttpControllerContext controllerContext, Type controllerType) w System.Web.Http.Dispatcher.DefaultHttpControllerFactory.CreateInstance (HttpControllerContext controllerContext, HttpContrcripateController) (HttpControllerContext controllerContext, String controllerName) w System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncInternal (HttpRequestMessage request, CancellationToken cancellationToken) w System.Web.Http.Dispatcell.HttpContrendollerAsyncInternal (HttpRequestMessage request, CancellationToken cancellationToken) w System.Web.Http.Dispatcell.HttpContrendól
Kontroler wygląda następująco:
public class ShoppingListController : System.Web.Http.ApiController
{
private Repositories.IProductListRepository _ProductListRepository;
public ShoppingListController(Repositories.IUserRepository userRepository,
Repositories.IProductListRepository productListRepository)
{
_ProductListRepository = productListRepository;
}
}
Mój plik Unity wygląda następująco:
<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>
Zauważ, że nie mam rejestracji samego kontrolera, ponieważ w poprzednich wersjach MVC fabryka kontrolerów zorientowała się, że zależności wymagają rozwiązania.
Wygląda na to, że nigdy nie dzwoniono do mojej fabryki kontrolerów.
źródło
GlobalConfiguration.Configuration.ServiceResolver.SetResolver()
?Jest tu lepsze rozwiązanie, które działa poprawnie
http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver
źródło
Możesz rzucić okiem na pakiet Unity.WebApi NuGet, który rozwiąże to wszystko, a także zapewni składniki IDisposable.
widzieć
http://nuget.org/packages/Unity.WebAPI
lub
http://www.devtrends.co.uk/blog/introducing-the-unity.webapi-nuget-package
źródło
UnityResolver
.Microsoft stworzył w tym celu pakiet.
Uruchom następujące polecenie z konsoli menedżera pakietów.
zainstaluj pakiet Unity.AspNet.WebApi
Jeśli masz już zainstalowany Unity, zapyta, czy chcesz nadpisać App_Start \ UnityConfig.cs. Odpowiedz nie i kontynuuj.
Nie trzeba zmieniać żadnego innego kodu, a DI (z jednością) będzie działać.
źródło
Miałem ten sam błąd i szukałem rozwiązań w Internecie przez kilka godzin. Ostatecznie okazało się, że muszę zarejestrować Unity PRZED wywołaniem WebApiConfig.Register. Mój global.asax wygląda teraz tak
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); } }
Dla mnie to rozwiązało problem, że Unity nie może rozwiązać zależności w moich kontrolerach
źródło
W niedawnym RC stwierdziłem, że nie ma już metody SetResolver. Aby włączyć IoC dla kontrolera i webapi, używam Unity.WebApi (NuGet) i następującego kodu:
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; } }
Używam również UnityConfiguration (również z NuGet) do magii IoC. ;)
źródło
Po przeczytaniu odpowiedzi nadal musiałem dużo kopać, aby wylądować w tej pułapce, więc tutaj jest to z korzyścią dla rówieśników: To wszystko, co musisz zrobić w ASP.NET 4 Web API RC (stan na 8 sierpnia 13):
I oto zależności wstawione do konstruktora bez kolejnej linii kodu!
UWAGA: otrzymałem tę informację z jednego z komentarzy na TYM blogu jego autora.
źródło
Krótkie podsumowanie dotyczące ASP.NET Web API 2.
Zainstaluj
Unity
z NuGet.Utwórz nową klasę o nazwie
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(); } }
Utwórz nową klasę o nazwie
UnityConfig
:public static class UnityConfig { public static void ConfigureUnity(HttpConfiguration config) { var container = new UnityContainer(); container.RegisterType<ISomethingRepository, SomethingRepository>(); config.DependencyResolver = new UnityResolver(container); } }
Edytuj App_Start -> WebApiConfig.cs
public static void Register(HttpConfiguration config) { UnityConfig.ConfigureUnity(config); ...
Teraz to zadziała.
Oryginalne źródło, ale nieco zmodyfikowane: https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection
źródło
Miałem ten sam wyjątek, aw moim przypadku wystąpił konflikt między plikami binarnymi MVC3 i MVC4. To uniemożliwiało prawidłową rejestrację moich kontrolerów w moim kontenerze IOC. Sprawdź swój plik web.config i upewnij się, że wskazuje poprawną wersję MVC.
źródło
Ten problem występuje z powodu rejestracji kontrolerów w Unity. Rozwiązałem to, używając rejestracji według konwencji, jak pokazano poniżej. W razie potrzeby odfiltruj wszelkie dodatkowe typy.
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);
Również powyższy przykład używa
AllClasses.FromLoadedAssemblies()
. Jeśli patrzysz na ładowanie zestawów ze ścieżki podstawowej, może to nie działać zgodnie z oczekiwaniami w projekcie interfejsu API sieci Web przy użyciu aparatu Unity. Proszę spojrzeć na moją odpowiedź na inne związane z tym pytanie. https://stackoverflow.com/a/26624602/1350747źródło
Miałem ten sam problem podczas korzystania z pakietu NuGet Unity.WebAPI. Problem polegał na tym, że pakiet nigdy nie dodał wywołania do
UnityConfig.RegisterComponents()
w moim Global.asax.Global.asax.cs powinien wyglądać tak:
public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { UnityConfig.RegisterComponents(); ... } }
źródło