[c#] Unity를 사용하여 ASP.NET Web API 컨트롤러에 종속성을 삽입 할 수 없음

ASP.NET WebAPI 컨트롤러에 종속성을 주입하기 위해 IoC 컨테이너를 사용하여 성공한 사람이 있습니까? 나는 그것을 작동시킬 수없는 것 같습니다.

이것이 제가 지금하고있는 일입니다.

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

종속성을 해결하기 위해 내 Unity 파일을 보지 않는 것 같으며 다음과 같은 오류가 발생합니다.

‘PersonalShopper.Services.WebApi.Controllers.ShoppingListController’유형의 컨트롤러를 작성하는 중에 오류가 발생했습니다. 컨트롤러에 매개 변수없는 공용 생성자가 있는지 확인하십시오.

System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create (HttpControllerContext controllerContext, Type controllerType) at System.Web.Http.Dispatcher.DefaultHttpControllerFactory.CreateInstance (HttpControllerContext controllerContext, HttpControllerDescriptor controllerDescriptor) at System.Web.Http.Dispatcher.DefaultHttpControllerFactory.CreateController (HttpControllerContext controllerContext, String controllerName) at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncInternal (HttpRequestMessage request, CancellationToken cancelToken) at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync (HttpRequestMessage request, CancellationToken cancelToken)

컨트롤러는 다음과 같습니다.

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


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

내 Unity 파일은 다음과 같습니다.

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

해당 컨트롤러 활성화기를 Unity 컨테이너 자체의 구현으로 등록했습니다.

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


답변

여기에 올바르게 작동하는 더 나은 솔루션이 있습니다.

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


답변

이 모든 것을 분류하고 IDisposable 구성 요소를 제공하는 Unity.WebApi NuGet 패키지를 살펴볼 수 있습니다.

보다

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

또는

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


답변

Microsoft는이를위한 패키지를 만들었습니다.

패키지 관리자 콘솔에서 다음 명령을 실행하십시오.

설치 패키지 Unity.AspNet.WebApi

Unity가 이미 설치되어있는 경우 App_Start \ UnityConfig.cs를 덮어 쓸지 묻는 메시지가 표시됩니다. 아니오라고 대답하고 계속하십시오.

다른 코드를 변경할 필요가 없으며 DI (통합 포함)가 작동합니다.


답변

나는 같은 오류가 있었고 몇 시간 동안 인터넷에서 해결책을 찾고있었습니다. 결국 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 메서드가 없다는 것을 알았습니다. 컨트롤러와 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;
    }
}

또한 IoC 마술을 위해 UnityConfiguration (NuGet에서도 제공)을 사용합니다. 😉


답변

답변을 읽은 후에도 여전히이 문제를 해결하기 위해 많은 작업을 수행해야했기 때문에 동료의 이익을 위해 여기에 있습니다. ASP.NET 4 Web API RC에서 수행해야 할 모든 작업입니다 (8 월 8 일 기준). ’13) :

  1. “Microsoft.Practices.Unity.dll”에 대한 참조 추가 [NuGet을 통해 추가 된 버전 3.0.0.0에 있습니다.]
  2. “Unity.WebApi.dll”에 대한 참조 추가 [NuGet을 통해 추가 된 버전 0.10.0.0에 있습니다.]
  3. Unity.WebApi 프로젝트에서 프로젝트에 추가 한 Bootstrapper.cs의 코드와 유사하게 컨테이너에 유형 매핑을 등록합니다.
  4. ApiController 클래스에서 상속하는 컨트롤러에서 매개 변수 유형을 매핑 된 유형으로 갖는 매개 변수화 된 생성자를 만듭니다.

자, 보라, 다른 코드 줄없이 생성자에 의존성을 주입 할 수 있습니다!

참고 : 블로그의 작성자가 작성한 댓글 중 하나에서이 정보를 얻었습니다 .