1

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.

ahmadali shafiee
  • 4,350
  • 12
  • 56
  • 91

1 Answers1

5

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:

  1. Having multiple constructors is an anti-pattern
  2. You are now using the service locator anti pattern for resolving the 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

Ric .Net
  • 5,540
  • 1
  • 20
  • 39
  • Thanks for the reason. but StructureMap supports multiple constructors. I've added this to my config and that worked :) `x.ForConcreteType().Configure.SelectConstructor(() => new AccountController());` so please update your answer so I check it as accepted. – ahmadali shafiee Mar 24 '15 at 23:08
  • @ahmadalishafiee: See my edit about the constructor. Also edited my answer as a reaction on your solution – Ric .Net Mar 25 '15 at 10:53