Structuremap does not work on MVC4
Asked Answered
N

4

12

I've used StructureMap in MVC2/3 many times without any concern, but I guess handling IoC is different in MVC4. When i used StructureMap for handling IoC in MVC4 I get the following exception.:

No parameterless constructor defined for this object

Why? I have not found any correct result in google except this: IoC Not Working In MVC4 These is my IoC classes:

public static class IoC {
    public static IContainer Initialize() {
        ObjectFactory.Initialize(x =>
                    {
                        x.Scan(scan =>
                        {
                            //scan.Assembly("DLL.Core");
                            scan.Assembly("DLL.CMS");
                            scan.TheCallingAssembly();
                            scan.WithDefaultConventions();
                        });
                        x.For<IDbContext>().Use<ModelEntities>();
                        x.For(typeof(IRepository<>)).Use(typeof(Repository<>));
                        x.For<IHttpControllerActivator>();
                        x.For<IController>();
                    });

        return ObjectFactory.Container;
    }

And SmDependencyResolver is:

    public class SmDependencyResolver : IDependencyResolver
{
    private readonly IContainer _container;

    public SmDependencyResolver(IContainer container)
    {
        _container = container;
    }

    public object GetService(Type serviceType)
    {
        if (serviceType == null) return null;
        try
        {
            return serviceType.IsAbstract || serviceType.IsInterface
                     ? _container.TryGetInstance(serviceType)
                     : _container.GetInstance(serviceType);
        }
        catch
        {

            return null;
        }
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return _container.GetAllInstances(serviceType).Cast<object>();
    }
}

And my error is:

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) +98
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache) +241 System.Activator.CreateInstance(Type type, Boolean nonPublic) +69
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +67

[InvalidOperationException: An error occurred when trying to create a controller of type 'Parsian.Web.Areas.Dashboard.Controllers.MemberController'. Make sure that the controller has a parameterless public constructor.]
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +182
System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +80
System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +74
System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +196 System.Web.Mvc.<>c__DisplayClass6.b__2() +49 System.Web.Mvc.<>c__DisplayClassb1.<ProcessInApplicationTrust>b__a() +13 System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +7 System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22
System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Func
1 func) +124 System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +98
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +50
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8862676 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184

Thanks for correct answers.

Nought answered 4/3, 2012 at 18:11 Comment(5)
Can you post the full error message? Do you set the SmDependencyResolver as DependencyResolver in the Global.asax or in the PreApplicationStartMethod?. Because I've just created a MVC4 project with the StructureMap.MVC3 nuget package and it works as excepted...Sophiasophie
i dont want use this package, I add only structuremap package (dll) to project with nuget.Nought
Just use the DefaultControllerFactory.Monkey
What is the meaning?How do this?Nought
Make sure you are wiring up the DependencyResolver in your global.asax, and that you are mapping the appropriate resolvers in your SM setup. That error is usually what you get when you don't do one of those two things.Traditional
N
10

oops.I found an emergency solution :) Try to implement a class from IControllerActivator

public class StructureMapControllerActivator : IControllerActivator
{
   private IContainer _container;
    
   public StructureMapControllerActivator(IContainer container)
   {
       _container = container;
   }
    
   public IController Create(RequestContext requestContext, Type controllerType)
   {
       return _container.GetInstance(controllerType) as IController;
   }
}

and then register it to the IoC class:

 x.For<IControllerActivator>().Use<StructureMapControllerActivator>();

and then enjoy it. Good luck

Nought answered 5/3, 2012 at 20:43 Comment(2)
This should not be needed with Structuremap. See this blog post on why the IControllerActivator extension point is in MVC3+.Kirimia
While IControllerActivator is not technically needed, you may still want one, at least durring development. Why? Well because if you don't and your DI container throws an error, then MVC will eat the error, and try again with Activator.CreateInstance, which could yield an error like the one above. This makes it hard to determine what went wrong. :-(Brindabrindell
M
3

If you remove any old configuration for structuremap and install structurmap.mvc4 from nuget then configure your IoC container, you don't have any problems.

Murtagh answered 19/10, 2012 at 20:57 Comment(0)
B
2

try adding this class as your ControllerFactory, I've actually seen the error above in MVC3 and this usually fixed it for me

public class StructureMapControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        try
        {
            return (controllerType == null)
                       ? base.GetControllerInstance(requestContext, controllerType)
                       : ObjectFactory.GetInstance(controllerType) as IController;
        }
        catch (Exception ex)
        {
            return null;
        }
    }
}
Brittney answered 5/3, 2012 at 13:19 Comment(2)
This is a very old way of implmenting dependency injection in MVC... Crica MVC1-2. MVC 3 and 4 implement IDependencyResolver as an interface to your IOC Container.Malamut
@Malamut Is IDependencyResolver responsible for injecting dependencies into my controller constructor?Monkey
E
0

Using StructureMap.MVC5.Update I had to do this or else the nested IContainer was already disposed (weird) :

public class StructureMapControllerActivator : IControllerActivator
{
    public IController Create(RequestContext requestContext, Type controllerType)
    {
        return StructuremapMvc.StructureMapDependencyScope.GetInstance(controllerType) as IController;
    }
}
Electroencephalogram answered 16/3, 2017 at 17:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.