I'm using StructureMap and ASP.Net Identity in my application. When I have this line in my Application_Start
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
and this is StructureMapControllerFactory
:
public class StructureMapControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null && requestContext.HttpContext.Request.Url != null)
throw new InvalidOperationException(string.Format("Page not found: {0}",
requestContext.HttpContext.Request.Url.AbsoluteUri.ToString(CultureInfo.InvariantCulture)));
return ObjectFactory.GetInstance(controllerType) as Controller;
}
}
return ObjectFactory.GetInstance(controllerType) as Controller;
throws a StructureMapConfigurationException
exception saying:
No default Instance is registered and cannot be automatically determined for type 'IUserStore<Person>'
but if I remove ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
line everything goes fine so it's StructureMap's problem not my code.
I think the exception is clear. It's probably about the AccountController from the Identity template, which comes with 2 constructors.
StructureMap will use the most greediest constructor by default. The template comes with 2 constructors, one default constructor and one constructor with an ApplicationUserManager
object.
Without StructureMap the default constructor is called and the ApplicationUserManager will be resolved using the service locator anti pattern.
StructureMap now must create the ApplicationUserManager
and because this is a concrete type it will try. If it was an abstract it will throw the exception right there. The ApplicationUserManager
however has a single constructor which needs an IUserStore<Person>
. Because this is an abstract and the container has no registration of this type, StructureMap is unable to create the type for you.
To solve this you should remove the default constructor and Register the ApplicationUserManager and depending services which is at least some component which, implements IUserStore.
Edit: While the solution you mentioned in the comments may work, this is not the preferable solution because of:
ApplicationUserManager
from the HttpContext
The templates that come with VS2013 need some work to use with dependency injection. This will cost some time. The good news is, it is possible and doable and will greatly improve your knowledge of Owin
, Asp.Net Identity
, Dependency Injection and SOLID design.
There are several blogs on how to start refactoring the templates to work with dependency injection. You could read about that here and here