Denetleyicide parametresiz bir genel oluşturucu hatası olduğundan emin olun


106

Ek bir kurucuya sahip olacak şekilde değiştirene kadar harika çalışan bu öğreticiyi takip ettim DbContext. Şu anda çözümle ilgili sorunlar yaşıyorum ve bunu düzeltmek için ne yapacağımı bilmiyorum. Onu parametresiz kurucuyu yakalamaya zorlamanın kolay bir yolu var mı yoksa buna yanlış bir şekilde mi yaklaşıyorum?

DbContext iki kurucu ile:

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

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

SiteController yapıcı:

private readonly IDashboardRepository _repo;

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

Depo:

DashboardDbContext _context;

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

UnityResolver kod:

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 Çağrısında Hata:

System.InvalidOperationException: 'SiteController' türünde bir denetleyici oluşturmaya çalışırken bir hata oluştu. Denetleyicinin parametresiz bir genel kurucuya sahip olduğundan emin olun.

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' yazın varsayılan bir kurucuya sahip değil.

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)

Öğretici harikaydı ve ikinci kurucuyu ekleyene kadar benim için iyi çalışıyordu.


2
Hata size bunun SiteControllerparametresiz bir kurucuya sahip olmaması gerektiğini söylüyor DashboardDbContext.
Neil Smith

Merhaba Smith.h.Neil, ancak bu hatayı yalnızca ek kurucu dbcontext'e eklendiğinde atar. Bunu kaldırırsam veya yorum yaparsam (ikinci kurucu) iyi çalışır.
scarpacci

İçin kurucuyu görebilir miyim SiteController?
Neil Smith

Ve DbContextdepoya enjekte ettiğinizi tahmin ediyorum ?
Neil Smith

@scarpacci Yaptığınız tek değişikliğin ikinci kurucuyu DbContext'ten kaldırmak olduğundan emin misiniz ? İkinci DbContext yapıcısına sahip olmayarak denetleyicinizin somutlaştırılmasını bir şekilde atlamadığınız sürece, hatanın DbContext yapıcılarına bağlı olmasının bir anlamı olmaz.
Asad Saeeduddin

Yanıtlar:


130

Olan, bu problem tarafından ısırılman . Temel olarak, denetleyicilerinizi konteynırınıza açıkça kaydetmemiş olmanızdır. Unity sizin için kayıtsız somut türleri çözmeye çalışır, ancak çözemediği için (yapılandırmanızdaki bir hatadan kaynaklanır), null döndürür. Boş değer döndürmeye zorlanır, çünkü Web API onuIDependencyResolver sözleşme . Unity null döndürdüğünden, Web API denetleyicinin kendisini oluşturmaya çalışır, ancak varsayılan bir kurucuya sahip olmadığı için "Denetleyicinin parametresiz bir genel kurucuya sahip olduğundan emin olun" istisnasını atar. Bu istisna mesajı yanıltıcıdır ve gerçek nedeni açıklamaz.

Denetleyicilerinizi açıkça kaydettirdiyseniz çok daha net bir istisna mesajı görürdünüz ve bu nedenle her zaman tüm kök türlerini açıkça kaydetmelisiniz.

Ancak elbette, yapılandırma hatası ikinci kurucuyu DbContext. Unity her zaman en çok argümana sahip kurucuyu seçmeye çalışır, ancak bu belirli kurucuyu nasıl çözeceği hakkında hiçbir fikri yoktur.

Yani asıl neden, Unity'nin otomatik kablolama yeteneklerini kullanarak DbContext. DbContextotomatik olarak kablolanmaması gereken özel bir türdür. Bu bir çerçeve türüdür ve bu nedenle bir fabrika temsilcisi kullanarak onu kaydetmeye geri dönmelisiniz :

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

LÜTFEN AKLINIZDA BULUNDURUN Projenizi yeniden oluşturduğunuzda oturum açma kimlik bilgilerinizi sıfırlayabilirsiniz ... bu çözümü uygulamaya çalışmadan önce lütfen: projenizi yeniden oluşturun, oturumu kapatıp tekrar açın, ancak o zaman - sayfanızı yenileyin ve sorunun devam edip etmediğini gözlemleyin
ymz

Teşekkür ederim - arka uç ekibimdeki bu dingleberries, birlik yapılandırmalarıyla birçok kuralı çiğniyor. Her takımın IOC kapsayıcılarını böyle kullanıp kullanmadığını merak etmeye başlıyorum.
Dagrooms

@Dagrooms: Pek çok geliştirici buna bayılıyor, ancak bu tüm DI Container'larda var olan bir sorun değil. Örneğin Basit Enjektör, böyle bir şey olması durumunda her zaman anlamlı bir hatanın ortaya çıkmasını sağlayacaktır. Bir başka iyi ipucu: Bir gelenek IDependencyResolverkullanmayın, IControllerActivatorbunun yerine yalnızca bir özel kullanın.
Steven

46

Benim durumumda, bunun nedeni enjekte edilen bağımlılığımın yapıcısı içindeki istisnaydı (örneğinizde - DashboardRepository kurucusunun içinde). İstisna, MVC altyapısının içinde bir yerde yakalandı. Bunu ilgili yerlere günlükler ekledikten sonra buldum.


7
Bu gerçekten önemli bir cevap. Görürken Unity ile kurulum sorunlarını takip etme tuzağına düşmek çok kolaydır, Make sure that the controller has a parameterless public constructor.ancak bağımlılığın ayarlanması oldukça olasıdır, ancak bağırsakların derinliklerinde bir istisna çözülmesini durdurmuştur.
Phil Cooper

2
Bu. Bir milyon kez! Ninject yapılandırmama bir bağımlılık haritası eklemeyi unuttum.
Tarps

Bağırsaklardaki derin istisnam, 'DateTime?' Olması gereken bir özellik türü 'string' idi. Bu yanıtı görmemiş olsaydım bunu aramazdım. Çok teşekkürler
Jazzy

Daha LousyErrorMessageException () gibi
Simon_Weaver

Günlüğü hangi ilgili yerlere yerleştirdiniz? Hata ayıklayıcıdan koştum, ancak tüm CLR istisnalarını kontrol ettiğimde bile bir istisna olmadı. Manuel kurucu çözümlemesi eklemek zorunda kaldım ve ancak o zaman hatayı aldım. Kullanılabilir bir hata almak için Teşhis'i eklememi söyledi, bu sonunda bana çalışacak bir şey verdi
Arjan

6

Aynı sorunu yaşadım ve UnityConfig.cs dosyasında değişiklikler yaparak çözdüm UnityConfig.cs dosyasındaki bağımlılık sorununu çözmek için eklemeniz gereken:

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

5

Ben de aynı sorunu yaşadım. Google'da iki gün aradım. Sonunda, sorunun Kontrolör yapıcısının erişim değiştiricisi olduğunu yanlışlıkla fark ettim. Ben koymadı publicDenetçi'nin yapıcı ardındaki anahtar kelimeyi.

public class MyController : ApiController
    {
        private readonly IMyClass _myClass;

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

Bu deneyimi başka bir cevap olarak ekliyorum, belki bir başkası da benzer bir hata yapmıştır.


4

Bazen arabiriminizi ContainerBootstraper.cs'de çözdüğünüz için hatayı yakalamak çok zordur. Benim durumumda, api denetleyicisine enjekte ettiğim arayüzün uygulanmasını çözerken bir hata oluştu. BootstraperContainer'ımdaki arayüzü container.RegisterType<IInterfaceApi, MyInterfaceImplementaionHelper>(new ContainerControlledLifetimeManager());
şu şekilde çözdüğümden hatayı bulamadım : sonra bootstrap konteynerime aşağıdaki satırı ekledim: container.RegisterType<MyController>(); bu yüzden projeyi derlediğimde derleyici şikayet etti ve yukarıdaki satırda durdu ve hatayı gösterdi .


0

Denetleyicinizde bir arabiriminiz varsa

public myController(IXInterface Xinstance){}

Bunları Bağımlılık Enjeksiyonu kabına kaydetmelisiniz.

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

0

Bir özelliği yanlışlıkla UnityContainer'da tanımladığım arabirim türü yerine belirli bir nesne türü olarak tanımladığımda bu hatayı aldım.

Örneğin:

UnityContainer'ı Tanımlama:

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

SiteController (yanlış yol - repo tipine dikkat edin):

private readonly DashboardRepository _repo;

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

SiteController (doğru yol):

private readonly IDashboardRepository _repo;

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

0

Aşağıdaki gibi türünüzün eşleşmelerine direnmek için UnityConfig.cs kullanıyorsanız .

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

**webApiConfig.cs**Konteyner hakkında bilgi vermelisiniz

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

0

Benim durumumda, Unity'nin kırmızı ringa balığı olduğu ortaya çıktı. Sorunum, .NET'in farklı sürümlerini hedefleyen farklı projelerin bir sonucuydu. Unity doğru kuruldu ve her şey konteynere doğru bir şekilde kaydedildi. Her şey iyi derlendi. Ancak tür bir sınıf kitaplığındaydı ve sınıf kitaplığı .NET Framework 4.0'ı hedefleyecek şekilde ayarlandı. Unity kullanan WebApi projesi .NET Framework 4.5'i hedefleyecek şekilde ayarlandı. Sınıf kitaplığını hedef 4.5 olarak değiştirmek benim için sorunu çözdü.

Bunu, DI yapıcısını yorumlayarak ve varsayılan kurucu ekleyerek keşfettim. Denetleyici yöntemlerini yorumladım ve NotImplementedException oluşturmalarını sağladım. Denetleyiciye ulaşabileceğimi doğruladım ve NotImplementedException'ımın denetleyiciyi iyi örneklediğini gördüm. Ardından, varsayılan kurucuda, Unity'ye güvenmek yerine bağımlılık zincirini manuel olarak başlattım. Hala derlendi, ancak çalıştırdığımda hata mesajı geri geldi. Bu, Unity resmin dışında olsa bile hatayı hala aldığımı doğruladı. Sonunda, zincirin en altından başladım ve her seferinde bir satırı yorumlayarak ve artık hata mesajını almayana kadar yeniden test ederek yukarı doğru ilerledim. Bu beni rahatsız eden sınıfa yönlendirdi ve oradan tek bir mecliste izole edildiğini anladım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.