Async MVC Action with Windsor Lock

I have an MVC5 application that uses Castle Windsor ( http://www.artisancode.co.uk/2014/04/integrating-windsor-castle-mvc/ ). I recently tried adding an Async method to an MVC controller. When I do this, I get the following error message:

The asynchronous method "test" returns a task that cannot be executed synchronously.

I created a new MVC application in VS and did not receive an error, so I assume that I left something from the Castle Windsor configuration? However, I do not know where to start, and I could not find any article when this helps.

Update question with code:

CastleWindsorActionInvoker.cs

public class CastleWindsorActionInvoker : ControllerActionInvoker { private readonly IKernel kernel; public CastleWindsorActionInvoker(IKernel kernel) { this.kernel = kernel; } protected override ActionExecutedContext InvokeActionMethodWithFilters(ControllerContext controllerContext, IList<IActionFilter> filters, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters) { foreach(IActionFilter filter in filters) { kernel.InjectProperties(null, filter); } return base.InvokeActionMethodWithFilters(controllerContext, filters, actionDescriptor, parameters); } protected override AuthorizationContext InvokeAuthorizationFilters(ControllerContext controllerContext, IList<IAuthorizationFilter> filters, ActionDescriptor actionDescriptor) { foreach(IAuthorizationFilter filter in filters) { Type type = filter.GetType(); IEnumerable<INamedInstanceAttribute> namedInstanceAttributes = type.GetCustomAttributes(typeof(INamedInstanceAttribute), false) as IEnumerable<INamedInstanceAttribute>; if(namedInstanceAttributes != null) { this.kernel.InjectProperties(namedInstanceAttributes, filter); } else { this.kernel.InjectProperties(null, filter); } } return base.InvokeAuthorizationFilters(controllerContext, filters, actionDescriptor); } } 

WindsorDependencyMvcResolver.cs

 public class WindsorDependencyMvcResolver : System.Web.Mvc.IDependencyResolver { public IWindsorContainer container { get; protected set; } public WindsorDependencyMvcResolver(IWindsorContainer container) { if(container == null) { throw new ArgumentNullException("container"); } this.container = container; } public object GetService(Type serviceType) { try { return container.Resolve(serviceType); } catch(ComponentNotFoundException) { return null; } } public IEnumerable<object> GetServices(Type serviceType) { return container.ResolveAll(serviceType).Cast<object>(); } } 

CastleWindsorMvcFactory.cs

 public class CastleWindsorMvcFactory : DefaultControllerFactory { private readonly IKernel kernel; public CastleWindsorMvcFactory(IKernel kernel) { this.kernel = kernel; } protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { if(controllerType == null) { throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path)); } Controller controller = (Controller)kernel.Resolve(controllerType); if(controller != null) { controller.ActionInvoker = kernel.Resolve<IActionInvoker>(); } return controller; } public override void ReleaseController(IController controller) { kernel.ReleaseComponent(controller); } } 

Global.asax

 ControllerBuilder.Current.SetControllerFactory(new CastleWindsorMvcFactory(container.Kernel)); DependencyResolver.SetResolver(new WindsorDependencyMvcResolver(container)); 

MVC action

 public async Task<ActionResult> Index() { return View(); } 
+5
source share
2 answers

I was working on something else and came across this article. Based on this, I changed my CastleWindsorActionInvoker to inherit from AsyncControllerActionInvoker, and I was able to run my asynchronous action.

Thanks for all the suggestions!

+2
source

Disclaimer : The links below are for a sample Github project . I have created.

I would suspect that the article recommends the wrong lifestyle for your controllers. I usually use Transient, like this ::

 public class ControllersInstaller : IWindsorInstaller { public void Install(IWindsorContainer container, IConfigurationStore store) { container.Register(Classes.FromThisAssembly() .BasedOn<IController>() .LifestyleTransient()); container.Register(Classes.FromThisAssembly() .BasedOn<IHttpController>() .LifestyleTransient()); } } 

Using this installer, this action resolves just fine:

 public async Task<ActionResult> Login(Models.LoginFormModel model, string returnUrl = "") { try { if (ModelState.IsValid) { /* ... more code ... */ } } catch (Exception ex) { HandleException(ex); } // If we got this far, something failed; redisplay form return View(model); } 
+1
source

All Articles