सुनिश्चित करें कि नियंत्रक के पास एक पैरामीटर रहित सार्वजनिक निर्माता त्रुटि है


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()

इनर एक्सेप्शन: 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
नील स्मिथ

Hi Smith.h.Neil, लेकिन यह केवल उस त्रुटि को फेंकता है जब अतिरिक्त कंस्ट्रक्टर को dbcontext में जोड़ा जाता है। अगर मैं इसे हटाता हूं या टिप्पणी करता हूं (दूसरा निर्माणकर्ता) तो यह ठीक काम करता है।
स्कारपिया

क्या मैं निर्माणकर्ता को देख सकता हूं SiteController?
नील स्मिथ

और मुझे लगता है कि आप DbContextभंडार में इंजेक्शन लगा रहे हैं ?
नील स्मिथ

@scarpacci क्या आप सुनिश्चित हैं कि केवल वही परिवर्तन जो आप कर रहे हैं DbContext से दूसरा निर्माणकर्ता निकाल रहा है? जब तक आप किसी तरह से दूसरे DbContext कंस्ट्रक्टर के द्वारा अपने कंट्रोलर की इंस्ट्रूमेंटेशन को दरकिनार नहीं करते हैं, तब तक DbContext के कंस्ट्रक्टर्स पर निर्भर होने की त्रुटि का कोई मतलब नहीं होगा।
असद सईदुद्दीन

जवाबों:


130

क्या हो रहा है कि आप इस समस्या से काट रहे हैं । असल में, क्या हुआ है कि आपने अपने कंटेनर में अपने नियंत्रकों को स्पष्ट रूप से पंजीकृत नहीं किया है। एकता आपके लिए अपंजीकृत ठोस प्रकारों को हल करने की कोशिश करती है, लेकिन क्योंकि यह इसे हल नहीं कर सकता है (आपके कॉन्फ़िगरेशन में त्रुटि के कारण), यह अशक्त है। यह अशक्त लौटने के लिए मजबूर है, क्योंकि वेब एपीआई IDependencyResolverअनुबंध के कारण ऐसा करने के लिए मजबूर करता है । चूंकि एकता अशक्त हो जाती है, इसलिए वेब एपीआई नियंत्रक को स्वयं बनाने की कोशिश करेगा, लेकिन चूंकि इसमें डिफ़ॉल्ट निर्माता नहीं है, इसलिए यह "यह सुनिश्चित करें कि नियंत्रक के पास एक पैरामीटर रहित सार्वजनिक निर्माता है" अपवाद को फेंक देगा। यह अपवाद संदेश भ्रामक है और वास्तविक कारण की व्याख्या नहीं करता है।

यदि आपने अपने नियंत्रकों को स्पष्ट रूप से पंजीकृत किया है, तो आपको एक बहुत स्पष्ट अपवाद संदेश दिखाई देगा, और इसीलिए आपको हमेशा सभी रूट प्रकारों को स्पष्ट रूप से पंजीकृत करना चाहिए।

लेकिन निश्चित रूप से, कॉन्फ़िगरेशन त्रुटि आपके द्वारा दूसरे निर्माता को अपने साथ जोड़ने से आती है DbContext। एकता हमेशा सबसे तर्कों के साथ कंस्ट्रक्टर को चुनने की कोशिश करती है, लेकिन यह नहीं पता है कि इस विशेष कंस्ट्रक्टर को कैसे हल किया जाए।

तो असली कारण यह है कि आप बनाने के लिए एकता की ऑटो-वायरिंग क्षमताओं का उपयोग करने की कोशिश कर रहे हैं DbContextDbContextएक विशेष प्रकार है जो ऑटो-वायर्ड नहीं होना चाहिए। यह एक फ्रेमवर्क प्रकार है और इसलिए आपको फ़ैक्टरी प्रतिनिधि का उपयोग करके इसे पंजीकृत करने के लिए वापस आना चाहिए :

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

कृपया ध्यान दें कि जब आप अपनी परियोजना का पुनर्निर्माण करते हैं तो आप अपने लॉगिन क्रेडेंशियल्स को रीसेट कर सकते हैं ... इस समाधान को लागू करने का प्रयास करने से पहले: कृपया अपनी परियोजना का निर्माण करें, अपने आप को लॉग आउट करें, फिर से फिर से, केवल तब - अपना पृष्ठ ताज़ा करें और देखें कि क्या समस्या बनी रहती है
यमज़

धन्यवाद - मेरी बैकएंड टीम पर ये डिंगलबेरी एकता के नियमों के साथ बहुत सारे नियम तोड़ती हैं। आश्चर्य है कि अगर हर टीम आईओसी कंटेनरों का उपयोग करती है, तो शुरू करना।
डैगरूम

@ डैगरूम: कई डिवेलपर्स इससे थोड़ा परेशान हैं, लेकिन यह कोई समस्या नहीं है जो सभी डीआई कंटेनरों में मौजूद है। उदाहरण के लिए सरल इंजेक्टर, हमेशा यह सुनिश्चित करेगा कि ऐसा होने की स्थिति में एक अभिव्यंजक त्रुटि का संकेत मिलता है। एक और अच्छा सुझाव: एक कस्टम का उपयोग न करें IDependencyResolverबल्कि केवल एक कस्टम का IControllerActivatorउपयोग करें।
स्टीवन

46

मेरे मामले में, यह मेरी इंजेक्टेड निर्भरता के निर्माता के अंदर अपवाद के कारण था (आपके उदाहरण में - डैशबोर्ड रिपॉजिटरी कंस्ट्रक्टर के अंदर)। अपवाद को MVC के बुनियादी ढांचे के अंदर कहीं पकड़ा गया था। प्रासंगिक स्थानों में लॉग जोड़ने के बाद मुझे यह मिला।


7
यह वास्तव में महत्वपूर्ण उत्तर है। देखने के दौरान एकता के साथ सेट-अप मुद्दों का पीछा करने के जाल में गिरना बहुत आसान है, Make sure that the controller has a parameterless public constructor.लेकिन यह बहुत संभव है कि निर्भरता सेट-अप हो लेकिन आंतों में गहरे एक अपवाद ने इसे हल होने से रोक दिया है।
फिल कूपर

2
यह। एक लाख बार! मैं अपने Ninject कॉन्फ़िगरेशन पर निर्भरता मानचित्र जोड़ना भूल गया।
ट्रैवो

आंत्र अपवाद में मेरा गहरा एक प्रकार का 'स्ट्रिंग' था जब इसे 'डेटटाइम' होना चाहिए था। नहीं देखा होगा कि मैं इस जवाब को नहीं देखा था। बहुत - बहुत धन्यवाद।
झाझी

LousyErrorMessageException ()
Simon_Weaver

आपने लॉग को किन प्रासंगिक स्थानों पर रखा? मैं डीबगर से भागा, लेकिन मुझे कोई अपवाद नहीं मिला, तब भी जब मैंने सभी सीएलआर अपवादों की जाँच की। मुझे मैनुअल कंस्ट्रक्टर रिज़ॉल्यूशन जोड़ना था और तभी मुझे त्रुटि मिली। इसने मुझे एक उपयोगी त्रुटि प्राप्त करने के लिए नैदानिक ​​जोड़ने के लिए कहा, कि आखिरकार मुझे काम करने के लिए कुछ दिया
अर्जन

6

मेरे पास एक ही मुद्दा था और मैंने इसे UnityConfig.cs फ़ाइल में परिवर्तन करके हल किया। UnityConfig.cs फ़ाइल में निर्भरता समस्या को हल करने के लिए आपको जोड़ना होगा:

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

4

कभी-कभी क्योंकि आप अपने इंटरफ़ेस को कंटेनरबूटस्ट्रैपर में हल कर रहे हैं। इसलिए त्रुटि को पकड़ना बहुत मुश्किल है। मेरे मामले में आपी नियंत्रक के लिए इंजेक्ट किए गए इंटरफ़ेस के कार्यान्वयन को हल करने में एक त्रुटि हुई थी। मुझे इस त्रुटि का पता नहीं चल पाया क्योंकि मैंने अपने बूटस्ट्रैपऑनर में इंटरफ़ेस को इस तरह से हल किया है: container.RegisterType<IInterfaceApi, MyInterfaceImplementaionHelper>(new ContainerControlledLifetimeManager());
तो मैंने अपने बूटस्ट्रैप कंटेनर में निम्न पंक्ति जोड़ दी है: container.RegisterType<MyController>(); इसलिए जब मैं परियोजना को संकलित करता हूं, तो कंपाइलर ने शिकायत की और उपरोक्त लाइन में रुक गया और त्रुटि दिखाई। ।


4

मुझे भी यही समस्या थी। मैंने इसे दो दिनों के लिए देखा। अंत में मैंने गलती से देखा कि समस्या कंट्रोलर के कंस्ट्रक्टर के एक्सेस मोडिफायर की थी। मैंने publicकंट्रोलर के कंस्ट्रक्टर के पीछे महत्वपूर्ण शब्द नहीं रखा ।

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

मुझे यह त्रुटि तब हुई है जब मैंने गलती से एक विशिष्ट ऑब्जेक्ट प्रकार के रूप में एक संपत्ति को परिभाषित किया, इंटरफ़ेस प्रकार के बजाय जो मैंने यूनिटीकोएंटर में परिभाषित किया है।

उदाहरण के लिए:

एकता को परिभाषित करने वाला:

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

मेरे मामले में, एकता एक लाल हेरिंग निकला। मेरी समस्या .NET के विभिन्न संस्करणों को लक्षित करने वाली विभिन्न परियोजनाओं का परिणाम थी। एकता को सही तरीके से सेट किया गया था और सब कुछ सही ढंग से कंटेनर के साथ पंजीकृत किया गया था। सब कुछ ठीक संकलित। लेकिन प्रकार एक क्लास लाइब्रेरी में था, और क्लास लाइब्रेरी .NET फ्रेमवर्क 4.0 को लक्षित करने के लिए सेट किया गया था। एकता का उपयोग कर WebApi प्रोजेक्ट .NET फ्रेमवर्क 4.5 को लक्षित करने के लिए सेट किया गया था। कक्षा पुस्तकालय को बदलने के लिए भी 4.5 को लक्षित करना मेरे लिए समस्या तय करता है।

मैंने डि कंस्ट्रक्टर की टिप्पणी करके और डिफॉल्ट कंस्ट्रक्टर को जोड़कर यह खोज की। मैंने नियंत्रक विधियों पर टिप्पणी की और उन्हें NotImplementedException फेंक दिया। मैंने पुष्टि की कि मैं नियंत्रक तक पहुंच सकता हूं, और मेरे NotImplementedException को देखकर मुझे लगा कि यह नियंत्रक को ठीक कर रहा है। इसके बाद, डिफॉल्ट कंस्ट्रक्टर में, मैंने मैन्युअल रूप से यूनिटी पर निर्भर रहने के बजाय निर्भरता श्रृंखला को तत्काल बदल दिया। यह अभी भी संकलित है, लेकिन जब मैंने इसे चलाया तो त्रुटि संदेश वापस आ गया। इसने मेरे लिए पुष्टि की कि मुझे तब भी त्रुटि मिली जब एकता तस्वीर से बाहर थी। अंत में, मैंने श्रृंखला के निचले भाग में शुरू किया और अपने तरीके से काम किया, एक बार में एक पंक्ति को टिप्पणी की और तब तक रिटायर रहा जब तक मुझे त्रुटि संदेश नहीं मिला। इसने मुझे आपत्तिजनक वर्ग की दिशा में इंगित किया, और वहाँ से मुझे पता चला कि यह एक ही सभा में अलग-थलग था।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.