异步 MVC 操作与温莎城堡
Async MVC Action with Castle Windsor
我有一个使用 Castle Windsor (http://www.artisancode.co.uk/2014/04/integrating-windsor-castle-mvc/) 的 MVC5 应用程序。我最近尝试在 MVC 控制器中添加异步方法。当我这样做时,我收到以下错误消息:
异步动作方法'test'returns一个Task,不能同步执行
我在 VS 中创建了一个新的 MVC 应用程序但没有收到错误,所以我猜我在 Castle Windsor 配置中遗漏了一些东西?但是我不知道从哪里开始,而且我一直找不到任何有帮助的文章。
正在用代码更新问题:
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 动作
public async Task<ActionResult> Index()
{
return View();
}
免责声明:以下链接适用于我创建的sample Github project。
我怀疑这篇文章向您的控制器推荐了错误的生活方式。我通常使用 Transient,like so:
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());
}
}
使用该安装程序,this action 解决得很好:
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);
}
我正在做其他事情,遇到了这个 article。基于它,我将我的 CastleWindsorActionInvoker 更改为从 AsyncControllerActionInvoker 继承,并且我能够 运行 我的异步操作。
感谢所有建议!
我有一个使用 Castle Windsor (http://www.artisancode.co.uk/2014/04/integrating-windsor-castle-mvc/) 的 MVC5 应用程序。我最近尝试在 MVC 控制器中添加异步方法。当我这样做时,我收到以下错误消息:
异步动作方法'test'returns一个Task,不能同步执行
我在 VS 中创建了一个新的 MVC 应用程序但没有收到错误,所以我猜我在 Castle Windsor 配置中遗漏了一些东西?但是我不知道从哪里开始,而且我一直找不到任何有帮助的文章。
正在用代码更新问题:
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 动作
public async Task<ActionResult> Index()
{
return View();
}
免责声明:以下链接适用于我创建的sample Github project。
我怀疑这篇文章向您的控制器推荐了错误的生活方式。我通常使用 Transient,like so:
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());
}
}
使用该安装程序,this action 解决得很好:
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);
}
我正在做其他事情,遇到了这个 article。基于它,我将我的 CastleWindsorActionInvoker 更改为从 AsyncControllerActionInvoker 继承,并且我能够 运行 我的异步操作。
感谢所有建议!