Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async MVC Action with Castle Windsor

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

The asynchronous action method 'test' returns a Task, which cannot be executed synchronously.

I created a new MVC application in VS and did not receive the error, so I'm guessing I'v left something out of the Castle Windsor configuration? However I've no idea where to begin and I've been unable to find any article when helps.

Updating 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();
        }
like image 763
markpirvine Avatar asked Oct 19 '22 05:10

markpirvine


1 Answers

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

Thanks for all suggestions!

like image 193
markpirvine Avatar answered Oct 29 '22 22:10

markpirvine