Troubleshooting StructureMap Dependency Injection with ASP.NET MVC

Recently I’ve been trying to get an MVC controller working with the StructureMap.MVC4 NuGet package. In the process, I got a rather uninformative error which had me stumped for a while.

Setting up my controller, I added my interface to the constructor as follows:

public LearningController(IInductionUnitOfWork inductionUnitOfWork)
{
    _inductionUnitOfWork = inductionUnitOfWork;
}

After doing this and setting up some other framework related stuff, I tested out my view. Navigating to the view resulted in the extremely useful error No parameterless constructor defined for this object.:

Server Error in '/' Application.

No parameterless constructor defined for this object.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.MissingMethodException: No parameterless constructor defined for this object.

Source Error: 
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
 Stack Trace:

[MissingMethodException: No parameterless constructor defined for this object.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +971
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +1067
System.Activator.CreateInstance(Type type, Boolean nonPublic) +574
System.Activator.CreateInstance(Type type) +464
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +355

 [InvalidOperationException: An error occurred when trying to create a controller of type 'SSW.Induction.WebUI.Controllers.LearningController'. Make sure that the controller has a parameterless public constructor.]
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +493
System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +702
System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +472
System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +657
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +427
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +359
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +324
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +1059
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +631

After much head scratching, I decided to resolve the dependency in a parameter-less constructor instead of letting the framework take care of it. My reasoning behind this was in the hope that this would expose the underlying error during dependency resolution. I added a parameter-less constructor as the error suggested, and called the StructureMap ObjectFactory from there, to resolve the dependency for my interface:

public LearningController()
{
	IInductionUnitOfWork l = StructureMap.ObjectFactory.GetInstance();
}

It worked! By calling GetInstance in this manner, the actual exception surfaces as follows:

Server Error in '/' Application.

StructureMap Exception Code:  202
No Default Instance defined for PluginFamily SSW.Induction.DataAccess.IDbContext, SSW.Induction.DataAccess, Version=0.11.5049.39157, Culture=neutral, PublicKeyToken=null 
  Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

 Exception Details: StructureMap.StructureMapException: StructureMap Exception Code:  202
No Default Instance defined for PluginFamily SSW.Induction.DataAccess.IDbContext, SSW.Induction.DataAccess, Version=0.11.5049.39157, Culture=neutral, PublicKeyToken=null

Source Error:

Line 15:         public LearningController()
Line 16:         {
Line 17:             IInductionUnitOfWork l = StructureMap.ObjectFactory.GetInstance();
Line 18:             var x = l.LearningItems.GetAll();
Line 19:         }

It turns out that I forgot to set up the IDbContext map correctly. The new error tells me this straight away, making the problem quite easy to resolve. After setting up the mapping for IDbContext, the view works straight away.

namespace MyProject.DataAccess.Properties
{
    public class AssemblyRegistry : Registry
    {
        public AssemblyRegistry()
        {
            For().Singleton().Use().Ctor("connectionString").Is(GetConnectionString());
        }
    }
}

In this example, the GetConnectionString() method gets the connection string from configuration. The Singleton() method ensures that only one instance of InductionContext is created.

Is this problem one that you’ve come across before? Do you have a different way of troubleshooting this type of issue? Please leave a comment and let me know.

Advertisement

2 thoughts on “Troubleshooting StructureMap Dependency Injection with ASP.NET MVC

  1. Csaba Benko November 5, 2015 / 13:20

    Thanks Daniel, this idea saved my day. I was struggling figuring out, where I’m missed the mapping in a class with several injected object by StructureMap. By initializing them directly it was easy to point to the wrong class and fix it. Thanks.
    Csaba

  2. dotnetchris December 17, 2015 / 00:05

    To anyone wondering why this technique can be so successful, MVC is going to execute any configure controller activator first. If the activator throws an unhandled exception it will fall back to the default activator which attempts to call new THEController() and that returns the “No parameterless constructor defined for this object.”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s