IT

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

lottoking 2020. 9. 3. 20:38
반응형

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


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

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

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

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

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

In my case, Unity turned out to be a red herring. My problem was a result of different projects targeting different versions of .NET. Unity was set up right and everything was registered with the container correctly. Everything compiled fine. But the type was in a class library, and the class library was set to target .NET Framework 4.0. The WebApi project using Unity was set to target .NET Framework 4.5. Changing the class library to also target 4.5 fixed the problem for me.

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

참고 URL : https://stackoverflow.com/questions/24254189/make-sure-that-the-controller-has-a-parameterless-public-constructor-error

반응형