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

나는 추가 생성자를 갖도록 수정 하기 전까지 훌륭하게 작동 한이 튜토리얼 을 따랐다 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)

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



답변

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

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

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

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

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


답변

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


답변

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

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


답변

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


답변

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

public class MyController : ApiController
    {
        private readonly IMyClass _myClass;

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

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


답변

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

public myController(IXInterface Xinstance){}

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

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


답변

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