컨트롤러에 매개 변수없는 공개 생성자 오류가 있는지 확인


105

나는 추가 생성자를 갖도록 수정 하기 전까지 훌륭하게 작동 한이 튜토리얼 을 따랐다 DbContext. 이제 해결에 문제가 있으며이 문제를 해결하기 위해 무엇을해야할지 모르겠습니다. 매개 변수가없는 생성자를 잡도록 강제하는 쉬운 방법이 있습니까? 아니면 잘못 접근하고 있습니까?

DbContext 두 개의 생성자 :

public class DashboardDbContext : DbContext
{
    public DashboardDbContext() : base("DefaultConnection") { }

    public DashboardDbContext(DbConnection dbConnection, bool owns)
        : base(dbConnection, owns) { }
}

SiteController 건설자:

private readonly IDashboardRepository _repo;

public SiteController(IDashboardRepository repo)
{
    _repo = repo;
}

저장소:

DashboardDbContext _context;

public DashboardRepository(DashboardDbContext context)
{
    _context = context;
}

UnityResolver 암호:

public class UnityResolver : IDependencyResolver
{
    private readonly IUnityContainer _container;

    public UnityResolver(IUnityContainer container)
    {
        _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()
    {
        _container.Dispose();
    }
}

WebApiConfig :

var container = new UnityContainer();
container.RegisterType<IDashboardRepository, DashboardRepository>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);

WebApi 호출 오류 :

System.InvalidOperationException : 'SiteController'유형의 컨트롤러를 만들려고 할 때 오류가 발생했습니다. 컨트롤러에 매개 변수없는 공용 생성자가 있는지 확인하십시오.

at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) 
at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request) 
at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken) 
at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__0.MoveNext()

InnerException : System.ArgumentException : 'Dashboard.Web.Controllers.SiteController'형식에 기본 생성자가 없습니다.

at System.Linq.Expressions.Expression.New(Type type) 
at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType) 
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator) 
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)

튜토리얼은 훌륭했고 두 번째 생성자를 추가 할 때까지 잘 작동했습니다.


2
오류는 SiteController매개 변수가없는 생성자가 있어야 한다는 것을 알려줍니다 DashboardDbContext.
Neil Smith

안녕하세요 Smith.h.Neil,하지만 dbcontext에 추가 생성자가 추가 될 때만 해당 오류가 발생합니다. 그것을 제거하거나 주석 처리하면 (두 번째 생성자) 제대로 작동합니다.
scarpacci

생성자를 볼 수 있습니까 SiteController?
Neil Smith

그리고 나는 당신이 DbContext저장소에 주입하고 있다고 생각 합니까?
Neil Smith

@scarpacci DbContext 에서 두 번째 생성자를 제거하는 것이 유일한 변경 사항이라고 확신합니까? 두 번째 DbContext 생성자가 없어서 컨트롤러의 인스턴스화를 우회하지 않는 한 오류가 DbContext의 생성자에 종속되는 것은 의미가 없습니다.
Asad Saeeduddin 2014-06-17

답변:


130

무슨 일이 일어나고 있는지는 당신 이이 문제에 물렸다는 것입니다 . 기본적으로 컨테이너에 컨트롤러를 명시 적으로 등록하지 않은 것입니다. Unity는 등록되지 않은 구체적인 유형을 해결하려고 시도하지만 해결할 수 없기 때문에 (구성 오류로 인해) null을 반환합니다. Web API가 IDependencyResolver계약 으로 인해 그렇게하도록 강제하기 때문에 null을 반환해야합니다 . Unity가 null을 반환하기 때문에 Web API는 컨트롤러 자체를 생성하려고 시도하지만 기본 생성자가 없기 때문에 "컨트롤러에 매개 변수없는 공개 생성자가 있는지 확인"예외가 발생합니다. 이 예외 메시지는 오해의 소지가 있으며 실제 원인을 설명하지 않습니다.

컨트롤러를 명시 적으로 등록했다면 훨씬 더 명확한 예외 메시지를 보았을 것이므로 항상 모든 루트 유형을 명시 적으로 등록해야합니다.

그러나 물론 구성 오류는 두 번째 생성자를 DbContext. Unity는 항상 인수가 가장 많은 생성자를 선택하려고하지만이 특정 생성자를 해결하는 방법을 모릅니다.

따라서 실제 원인은 Unity의 자동 연결 기능을 사용하여 DbContext. DbContext자동 연결되어서는 안되는 특수 유형입니다. 프레임 워크 유형 이므로 팩토리 대리자를 사용하여 등록하는 것으로 대체 해야합니다 .

container.Register<DashboardDbContext>(
    new InjectionFactory(c => new DashboardDbContext())); 

참고 사항 이 솔루션주십시오을 적용하기 전에 ... 프로젝트 당신이 당신의 로그인 자격 증명을 재설정 할 수 있습니다를 재 구축 프로젝트를 다시 자신을 로그 아웃 한 후 다시에 만 다음 - 페이지를 새로 고침하고 문제가 지속되면 관찰
ymz

감사합니다. 백엔드 팀의이 딩글 베리는 유니티 구성으로 많은 규칙을 위반합니다. 이것이 모든 팀이 IOC 컨테이너를 사용하는 방법인지 궁금해지기 시작했습니다.
Dagrooms

@Dagrooms : 많은 개발자들이이 문제에 대해 조금씩 알고 있지만 모든 DI 컨테이너에 존재하는 문제는 아닙니다. 예를 들어 Simple Injector는 그러한 일이 발생하는 경우 항상 표현 오류가 표시되도록 보장합니다. 또 다른 좋은 팁 : 사용자 지정을 사용하지 말고 대신 IDependencyResolver사용자 지정 만 사용하십시오 IControllerActivator.
Steven

46

제 경우에는 삽입 된 종속성의 생성자 내부의 예외 때문이었습니다 (예 : DashboardRepository 생성자 내부). MVC 인프라 내부 어딘가에서 예외가 발견되었습니다. 관련 장소에 로그를 추가 한 후 이것을 발견했습니다.


7
이것은 정말 중요한 대답입니다. 볼 때 Unity로 설정 문제를 쫓는 함정에 빠지기는 매우 쉽지만 Make sure that the controller has a parameterless public constructor.종속성이 설정되었을 가능성이 크지 만 내부의 예외로 인해 해결이 중단되었습니다.
필 쿠퍼

2
이. 백만 번! Ninject 구성에 종속성 맵을 추가하는 것을 잊었습니다.
Travo

내 깊숙한 곳 예외는 'DateTime?'이어야 할 때 '문자열'의 속성 유형이었습니다. 이 대답을 보지 못했다면 그것을 찾지 못했을 것입니다. 정말 감사합니다.
Jazzy

더 LousyErrorMessageException ()와 같은
Simon_Weaver

로그를 어떤 관련 장소에 배치 했습니까? 디버거에서 실행했지만 모든 CLR 예외를 확인한 경우에도 예외가 없습니다. 수동 생성자 해결을 추가해야했지만 오류가 발생했습니다. 사용 가능한 오류를 얻기 위해 Diagnostic을 추가하라고했는데 결국 작업 할 수있는 무언가를주었습니다
Arjan

6

동일한 문제가 발생하여 UnityConfig.cs 파일을 변경하여 해결했습니다. UnityConfig.cs 파일에서 종속성 문제를 해결하려면 다음을 추가해야합니다.

public static void RegisterComponents()    
{
    var container = new UnityContainer();
    container.RegisterType<ITestService, TestService>();
    DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}

4

때로는 ContainerBootstraper.cs에서 인터페이스를 해결하기 때문에 오류를 포착하기가 매우 어렵습니다. 제 경우에는 API 컨트롤러에 삽입 한 인터페이스의 구현을 해결하는 데 오류가 발생했습니다. 내 bootstraperContainer에서 인터페이스를 container.RegisterType<IInterfaceApi, MyInterfaceImplementaionHelper>(new ContainerControlledLifetimeManager());
다음 과 같이 해결했기 때문에 오류를 찾을 수 없습니다. 그런 다음 부트 스트랩 컨테이너에 다음 줄을 추가했습니다. container.RegisterType<MyController>(); 그래서 프로젝트를 컴파일 할 때 컴파일러가 불평하고 위 줄에서 중지하고 오류를 표시했습니다. .


4

나는 같은 문제가 있었다. 나는 이틀 동안 그것을 봤다. 마침내 문제가 컨트롤러 생성자의 액세스 수정 자라는 것을 우연히 발견했습니다. publicController의 생성자 뒤에 핵심 단어를 넣지 않았습니다 .

public class MyController : ApiController
    {
        private readonly IMyClass _myClass;

        public MyController(IMyClass myClass)
        {
            _myClass = myClass;
        }
    }

나는이 경험을 다른 대답으로 추가하면 다른 사람이 비슷한 실수를했을 수 있습니다.


0

컨트롤러에 인터페이스가있는 경우

public myController(IXInterface Xinstance){}

종속성 주입 컨테이너에 등록해야합니다.

container.Bind<IXInterface>().To<XClass>().InRequestScope();

0

UnityContainer에서 정의한 인터페이스 유형 대신 실수로 속성을 특정 객체 유형으로 정의하면이 오류가 발생합니다.

예를 들면 :

UnityContainer 정의 :

var container = new UnityContainer();
container.RegisterInstance(typeof(IDashboardRepository), DashboardRepository);
config.DependencyResolver = new UnityResolver(container);

SiteController (잘못된 방법-저장소 유형 알림) :

private readonly DashboardRepository _repo;

public SiteController(DashboardRepository repo)
{
    _repo = repo;
}

SiteController (올바른 방법) :

private readonly IDashboardRepository _repo;

public SiteController(IDashboardRepository repo)
{
    _repo = repo;
}

0

UnityConfig.cs 를 사용하여 아래와 같이 유형의 매핑에 저항 하는 경우 .

public static void RegisterTypes(IUnityContainer container)
    {
     container.RegisterType<IProductRepository, ProductRepository>();
    }

**webApiConfig.cs**컨테이너에 대해 알려 주셔야합니다.

config.DependencyResolver = new Unity.AspNet.WebApi.UnityDependencyResolver(UnityConfig.Container);

0

제 경우에는 Unity가 붉은 청어로 밝혀졌습니다. 내 문제는 다른 버전의 .NET을 대상으로하는 다른 프로젝트의 결과였습니다. Unity가 올바르게 설정되었고 모든 것이 컨테이너에 올바르게 등록되었습니다. 모든 것이 잘 컴파일되었습니다. 그러나 형식은 클래스 라이브러리에 있었고 클래스 라이브러리는 .NET Framework 4.0을 대상으로 설정되었습니다. Unity를 사용하는 WebApi 프로젝트는 .NET Framework 4.5를 대상으로 설정되었습니다. 4.5를 대상으로 클래스 라이브러리를 변경하면 문제가 해결되었습니다.

DI 생성자를 주석 처리하고 기본 생성자를 추가하여 이것을 발견했습니다. 컨트롤러 메서드를 주석 처리하고 NotImplementedException을 throw했습니다. 컨트롤러에 도달 할 수 있음을 확인했고 NotImplementedException을보고 컨트롤러를 인스턴스화하고 있다고 말했습니다. 다음으로 기본 생성자에서 Unity에 의존하는 대신 종속성 체인을 수동으로 인스턴스화했습니다. 여전히 컴파일되었지만 실행했을 때 오류 메시지가 다시 나타났습니다. 이것은 Unity가 그림을 벗어 났을 때에도 여전히 오류가 있음을 확인했습니다. 마지막으로, 나는 체인의 맨 아래에서 시작하여 한 번에 한 줄씩 주석 처리하고 더 이상 오류 메시지가 나타나지 않을 때까지 다시 테스트했습니다. 이것은 저를 불쾌한 학급의 방향으로 이끌었고 거기서 저는 그것이 단일 어셈블리로 분리되어 있음을 알아 냈습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.