Problem
I'm using Unity as IoC and that worked fine, but as I keep adding functionality, it becomes increasingly difficult to pinpoint any errors, because Unity provides an error that is the symptom of the error, not the actual error:
"Message":"An error has occurred.","ExceptionMessage":"An error occurred
when trying to create a controller of type 'MyController'. Make sure that the
controller has a parameterless public
constructor.","ExceptionType":"System.InvalidOperationException"
Background
I have an MVC Web Api controller that has a dependency on a Manager instance (from domain):
public class MyController : ApiController
{
private IMyManager MyManager { get; set; }
public MyController(IMyManager myManager)
{
this.MyManager = myManager;
}
...
}
The above error occurs because IoC mapping of the IMyManager fails. As it fails, I have no parameter, meaning that MyController is called using a parameterless constructor, but since it doesn't exist (and shouldn't) I get the above error.
What I have tried
So, the error I get is not the 'real' error. The obvious thing is to make sure that every new implementation is registered under IoC, I checked and they are. I do it manually to keep things manageable (oh the irony!).
I do that like this:
container.RegisterType<IMyManager, MyManager>();
But, that's not the issue.
One fix I did was a circular dependency. I changed all involved constructors and methods to use property values, not instances. I checked all involved classes and there are no longer any circular dependencies.
Yet, the problem still occurs.
The question
What can I do to find out the actual problem? Manually checking dependencies is way too much overhead, because the structure is an intricate web of deeper dependencies. And this will get worse as the app matures.
Alternatively, if Unity just always obscures these messages (without being able to fix that), are there alternatives out there that do provide worthwhile error information?
UPDATE
Per request, the full error message (though I don't think the stacktrace is very helpful):
{"Message":"An error has occurred.","ExceptionMessage":"An error occurred when trying to create a controller of type 'MyController'. Make sure that the controller has a parameterless public constructor.","ExceptionType":"System.InvalidOperationException","StackTrace":" 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.<SendAsync>d__1.MoveNext()","InnerException":{"Message":"An error has occurred.","ExceptionMessage":"Type 'MyProject.Web.Api.Controllers.MyController' does not have a default constructor","ExceptionType":"System.ArgumentException","StackTrace":" 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)"}}
UPDATE 2
I dug a little deeper and checked all dependencies (they are pretty massive), but everything is registered and loaded correctly. There also aren't any circular dependencies, so as far as I can tell everything 'should' work. Since it doesn't I conclude that there's some error happening that is not being thrown up.
I found it, the problem was that I am remaking existing code, in the same solution, meaning that there's going to be duplicate files with identical names.
In this particular case I had an interface that was exactly the same as a previously existing one. Somewhere deep in the code I used the wrong namespace, meaning that the IoC mapping was incorrect.
So, something like this:
I have:
old.managers.IMyManager
and
new.managers.IMyManager
What I was doing in the mapping was:
container.RegisterType<IMyManager, MyManager>();
where IMyManager in this case is new.managers.IMyManager, as it should be.
One of the consumers of this dependency expected IMyManager of namespace old.managers.
Updating the consumer to use the new namespace fixed it.