Убедитесь, что контроллер имеет ошибку открытого конструктора без параметров


Я следил за этим учебник, который работал отлично, пока я не изменил мой 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:

5 82

5 ответов:

происходит то, что тебя укусил проблема. В основном, произошло то, что вы не зарегистрировали свои контроллеры явно в своем контейнере. Unity пытается разрешить незарегистрированные конкретные типы для вас, но поскольку он не может разрешить его (вызванный ошибкой в вашей конфигурации), он возвращает null. Он вынужден возвращать null, потому что веб-API заставляет его делать это из-за IDependencyResolver контракт. Поскольку 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>(); поэтому, когда я компилирую проект, компилятор жаловался и остановился в строке выше и показал ошибку.

у меня была та же проблема. Я гуглил его в течение двух дней. Наконец я случайно заметил, что проблема была модификаторы доступа конструктора контроллера. Я не ставил public ключевое слово за конструктором контроллера.

public class MyController : ApiController
    {
        private readonly IMyClass _myClass;

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

Я добавляю этот опыт в качестве другого ответа, возможно, кто-то еще сделал аналогичную ошибку.