2
Vote

problem with PUT POST AND DELETE Requests using API

description

"ExceptionType":"EFMVC.CommandProcessor.Command.CommandHandlerNotFoundException","Message":"Command handler not found for command type: EFMVC.Domain.Commands.DeleteCategoryCommand","StackTrace":" at EFMVC.CommandProcessor.Dispatcher.DefaultCommandBus.Submit[TCommand](TCommand command)
 
I'm not sure how to fix it. I've spent hours trying to work through or around it with no luck.

comments

hooked82 wrote Jun 16, 2012 at 9:21 PM

This is a major problem for me as well. As it currently sits, the Web API is useless as I can't run any commands because the DependencyResolver is not available in the DefaultCommandBus.

Repro Steps:
  1. Setup Autofac DI in the Bootstrapper.cs
  2. Run any of the existing Commands, or create a new one by doing a POST, PUT or DELETE.
  3. Call commandBus.Submit(command)
  4. See var handler = DependencyResolver.Current.GetService<ICommandHandler<TCommand>>(); returning null.
In Step 4, the handler is null, which is why we get the CommandHandlerNotFoundException(). The cause of this is becuase "DependencyResolver.Current" is actually System.Web.Mvc.DependencyResolver.DefaultDependencyResolver

If I replace the DependencyResolver.Current with GlobalConfiguration.Configuration.DependencyResolver, it gives me Autofac.Integration.WebApi.AutofacWebApiDependencyResolver, but then I get the following error message:

No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being reqested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.

BTW, this is after updating MVC4 to the Release Candidate, although I was having the exact same issue prior to updating.

Please help!! I'm at a standstill right now and am just about to drop EFMVC as I can't use it at all at this point.

tk_gautam wrote Jul 19, 2012 at 7:29 PM

Hi Guys!!!
This is the exact problem we are running into as well. Did you guys or anyone else find a fix for this issue? If not, how are you tackling this issue?

Please let us know, we would really appreciate it.
Thanks,
GT

hooked82 wrote Jul 22, 2012 at 6:38 PM

So here's how I was able to work around this, which seems very hacky and not an actual fix:

In your Bootstrapper.cs in the API project, when you set your dependency resolver, I had to set both the API and the MVC resolver:

var resolver = new AutofacWebApiDependencyResolver(container);
var resolve = new AutofacDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
DependencyResolver.SetResolver(resolve);

This allows me to access the API Dependency Resolver while in the API Controllers and when in the DefaultCommandBus when submitting a command, I'm able to access the DR by:

var handler = DependencyResolver.Current.GetService<ICommandHandler<TCommand>>();

I would really love get an actual solution/answer on this, rather than have to hack this by setting the Dependency Resolver twice.

tk_gautam wrote Jul 22, 2012 at 10:17 PM

Hi,
I tried the above code you mentioned (register both the MVC and webapi controllers) I get the same exact error as specified above by you -
"No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being reqested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself."

So you couldn't go beyond this point and get it to work? Please let me know.

Thanks,
Gautam

tk_gautam wrote Jul 27, 2012 at 12:03 PM

Finally I am able to get it to work, I found one solution on google. Basically I added a parameterized constructor to the DefaultCommandBus and passed in Autofac's IComponentContext instance ( Autofac injects this into the constructor) and then I used this instance to instantiate the commanhandler. So here's how I did it -
private readonly IComponentContext _context;
    public DefaultCommandBus(IComponentContext context)
    {
        _context = context;
    }
and var handler = _context.Resolve<ICommandHandler<TCommand>>(); instead of var handler = DependencyResolver.Current.GetService<ICommandHandler<TCommand>>();.
Hope this helps.

lowercase_g wrote Jan 2, 2013 at 6:39 AM

tk_gautam that worked perfectly!