Saya telah mengikuti tutorial ini yang berhasil dengan baik, sampai saya memodifikasi saya DbContext
untuk memiliki konstruktor tambahan. Saya sekarang mengalami masalah dengan resolusi dan tidak yakin apa yang harus dilakukan untuk memperbaikinya. Apakah ada cara mudah untuk memaksanya mengambil konstruktor tanpa parameter atau saya melakukan pendekatan yang salah?
DbContext
dengan dua konstruktor:
public class DashboardDbContext : DbContext
{
public DashboardDbContext() : base("DefaultConnection") { }
public DashboardDbContext(DbConnection dbConnection, bool owns)
: base(dbConnection, owns) { }
}
SiteController
konstruktor:
private readonly IDashboardRepository _repo;
public SiteController(IDashboardRepository repo)
{
_repo = repo;
}
Gudang:
DashboardDbContext _context;
public DashboardRepository(DashboardDbContext context)
{
_context = context;
}
UnityResolver
kode:
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);
Kesalahan dari Panggilan WebApi:
System.InvalidOperationException: Terjadi kesalahan saat mencoba membuat pengontrol berjenis 'SiteController'. Pastikan bahwa pengontrol memiliki konstruktor publik tanpa parameter.
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: Jenis 'Dashboard.Web.Controllers.SiteController' tidak memiliki konstruktor default.
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)
Tutorialnya sangat bagus dan telah bekerja dengan baik untuk saya sampai saya menambahkan konstruktor kedua.
sumber
SiteController
itulah yang harus memiliki konstruktor tanpa parameter, bukanDashboardDbContext
.SiteController
?DbContext
ke dalam repositori?Jawaban:
Apa yang terjadi adalah Anda digigit oleh masalah ini . Pada dasarnya, yang terjadi adalah Anda tidak mendaftarkan pengontrol Anda secara eksplisit di penampung Anda. Unity mencoba menyelesaikan jenis beton yang tidak terdaftar untuk Anda, tetapi karena Unity tidak dapat menyelesaikannya (disebabkan oleh kesalahan dalam konfigurasi Anda), ia mengembalikan null. Itu dipaksa untuk mengembalikan nol, karena API Web memaksanya untuk melakukannya karena
IDependencyResolver
kontrak. Karena Unity mengembalikan null, API Web akan mencoba membuat pengontrol itu sendiri, tetapi karena tidak memiliki konstruktor default, ia akan menampilkan pengecualian "Pastikan pengontrol memiliki konstruktor publik tanpa parameter". Pesan pengecualian ini menyesatkan dan tidak menjelaskan penyebab sebenarnya.Anda akan melihat pesan pengecualian yang lebih jelas jika Anda mendaftarkan pengontrol Anda secara eksplisit, dan itulah mengapa Anda harus selalu mendaftarkan semua jenis root secara eksplisit.
Tapi tentu saja, kesalahan konfigurasi berasal dari Anda menambahkan konstruktor kedua ke file
DbContext
. Unity selalu mencoba untuk memilih konstruktor dengan argumen terbanyak, tetapi tidak tahu bagaimana menyelesaikan konstruktor khusus ini.Jadi, penyebab sebenarnya adalah Anda mencoba menggunakan kemampuan kabel otomatis Unity untuk membuat file
DbContext
.DbContext
adalah tipe khusus yang tidak boleh terhubung secara otomatis. Ini adalah jenis kerangka kerja dan oleh karena itu Anda harus mundur untuk mendaftarkannya menggunakan delegasi pabrik :sumber
IDependencyResolver
tapi hanya gunakan customIControllerActivator
saja.Dalam kasus saya, itu karena pengecualian di dalam konstruktor ketergantungan saya yang disuntikkan (dalam contoh Anda - di dalam konstruktor DashboardRepository). Pengecualian tertangkap di suatu tempat di dalam infrastruktur MVC. Saya menemukan ini setelah saya menambahkan log di tempat yang relevan.
sumber
Make sure that the controller has a parameterless public constructor.
tetapi sangat mungkin dependensi sudah diatur tetapi pengecualian jauh di dalam perut telah menghentikannya diselesaikan.Saya memiliki masalah yang sama dan saya mengatasinya dengan membuat perubahan pada file UnityConfig.cs Untuk menyelesaikan masalah ketergantungan pada file UnityConfig.cs Anda harus menambahkan:
sumber
Terkadang karena Anda menyelesaikan antarmuka Anda di ContainerBootstraper.cs, sangat sulit untuk menangkap kesalahannya. Dalam kasus saya, ada kesalahan dalam menyelesaikan implementasi antarmuka yang telah saya masukkan ke pengontrol api. Saya tidak dapat menemukan kesalahan karena saya telah menyelesaikan antarmuka di bootstraperContainer saya seperti ini:
container.RegisterType<IInterfaceApi, MyInterfaceImplementaionHelper>(new ContainerControlledLifetimeManager());
maka saya telah menambahkan baris berikut di wadah bootstrap saya:
container.RegisterType<MyController>();
jadi ketika saya menyusun proyek, kompilator mengeluh dan berhenti di baris di atas dan menunjukkan kesalahan .sumber
Saya memiliki masalah yang sama. Saya mencarinya di Google selama dua hari. Akhirnya saya secara tidak sengaja memperhatikan bahwa masalahnya adalah pengubah akses dari konstruktor Controller. Saya tidak meletakkan
public
kata kunci di belakang konstruktor Pengendali.Pengalaman ini saya tambahkan sebagai jawaban lain mungkin orang lain melakukan kesalahan serupa.
sumber
Jika Anda memiliki antarmuka di pengontrol Anda
Anda harus mendaftarkannya ke wadah Injeksi Ketergantungan.
sumber
Saya mendapat kesalahan ini ketika saya secara tidak sengaja mendefinisikan properti sebagai tipe objek tertentu, alih-alih tipe antarmuka yang telah saya definisikan di UnityContainer.
Sebagai contoh:
Mendefinisikan UnityContainer:
SiteController (cara yang salah - perhatikan jenis repo):
SiteController (dengan cara yang benar):
sumber
Jika Anda menggunakan UnityConfig.cs untuk mendaftarkan ulang pemetaan tipe Anda seperti di bawah ini.
Anda harus memberi tahu
**webApiConfig.cs**
tentang Containersumber
Dalam kasus saya, Unity ternyata adalah ikan haring merah. Masalah saya adalah hasil dari proyek berbeda yang menargetkan versi berbeda dari .NET. Unity telah disiapkan dengan benar dan semuanya telah didaftarkan dengan container dengan benar. Semuanya dikompilasi dengan baik. Tapi jenisnya berada di perpustakaan kelas, dan perpustakaan kelas ditetapkan ke target .NET Framework 4.0. Proyek WebApi menggunakan Unity ditetapkan untuk menargetkan .NET Framework 4.5. Mengubah perpustakaan kelas ke target 4,5 juga memperbaiki masalah saya.
Saya menemukan ini dengan mengomentari konstruktor DI dan menambahkan konstruktor default. Saya mengomentari metode pengontrol dan meminta mereka membuang NotImplementedException. Saya mengonfirmasi bahwa saya dapat menjangkau pengontrol, dan melihat NotImplementedException saya memberi tahu saya bahwa itu membuat instance pengontrol baik-baik saja. Selanjutnya, di konstruktor default, saya membuat instance rantai dependensi secara manual daripada mengandalkan Unity. Itu masih dikompilasi, tetapi ketika saya menjalankannya pesan kesalahan muncul kembali. Ini menegaskan bagi saya bahwa saya masih mendapatkan kesalahan bahkan ketika Unity tidak ada dalam gambar. Akhirnya, saya mulai dari bagian bawah rangkaian dan melanjutkan ke atas, mengomentari satu baris pada satu waktu dan menguji ulang sampai saya tidak lagi mendapatkan pesan kesalahan. Ini mengarahkan saya ke arah kelas yang melanggar, dan dari sana saya menemukan bahwa kelas itu diisolasi ke satu majelis.
sumber