使用Umbraco 7的异步控制器操作返回字符串

是否可以在Umbraco SurfaceController(和UmbracoApiController)中使用异步操作

我尝试了以下代码

public async Task HandleLogin(LoginViewModel model) { await Task.Delay(1000); return PartialView("Login", model); } 

虽然它在调用动作时正确编译,但是一旦命中await,动作似乎就会返回,并返回一个字符串

System.Threading.Tasks.Task`1 [System.Web.Mvc.ActionResult]

控制器当然inheritance自SurfaceController ,我想知道这是不是问题?

如果这不可能,是否有任何变通方法来实现异步操作行为?

任何帮助都会感激不尽!

Umbraco中的SurfaceControllers最终派生自System.Web.Mvc.Controller但是它们具有自定义动作调用程序( RenderActionInvoker )集。

RenderActionInvokerinheritance自ContollerActionInvoker 。 为了处理异步操作,它应该从AsyncContolkerActionInvoker派生。 RenderActionInvoker仅覆盖findaction方法,因此更改为从AsyncContolkerActionInvoker派生很容易。

一旦我使用此更改重新编译Umbraco.Web,异步操作就可以正常工作。

我猜你可以在每个class级上指定一个新的actioninvoker,而不是重新编译整个项目

 public class RenderActionInvokerAsync : System.Web.Mvc.Async.AsyncControllerActionInvoker { protected override ActionDescriptor FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, string actionName) { var ad = base.FindAction(controllerContext, controllerDescriptor, actionName); if (ad == null) { //check if the controller is an instance of IRenderMvcController if (controllerContext.Controller is IRenderMvcController) { return new ReflectedActionDescriptor( controllerContext.Controller.GetType().GetMethods() .First(x => x.Name == "Index" && x.GetCustomAttributes(typeof(NonActionAttribute), false).Any() == false), "Index", controllerDescriptor); } } return ad; } } public class TestController : SurfaceController { public TestController() { this.ActionInvoker = new RenderActionInvokerAsync(); } public async Task Test() { await Task.Delay(10000); return PartialView("TestPartial"); } } 

虽然没有测试过这种做事方式。

仅供参考我为跟踪器添加了一个问题: http : //issues.umbraco.org/issue/U4-5208

虽然有一个工作:

创建自定义异步呈现操作调用(如上所述):

 public class FixedAsyncRenderActionInvoker : System.Web.Mvc.Async.AsyncControllerActionInvoker { protected override ActionDescriptor FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, string actionName) { var ad = base.FindAction(controllerContext, controllerDescriptor, actionName); if (ad == null) { //check if the controller is an instance of IRenderMvcController if (controllerContext.Controller is IRenderMvcController) { return new ReflectedActionDescriptor( controllerContext.Controller.GetType().GetMethods() .First(x => x.Name == "Index" && x.GetCustomAttributes(typeof(NonActionAttribute), false).Any() == false), "Index", controllerDescriptor); } } return ad; } } 

创建自定义渲染mvc控制器:

 public class FixedAsyncRenderMvcController : RenderMvcController { public FixedAsyncRenderMvcController() { this.ActionInvoker = new FixedAsyncRenderActionInvoker(); } } 

创建自定义渲染控制器工厂:

 public class FixedAsyncRenderControllerFactory : RenderControllerFactory { public override IController CreateController(RequestContext requestContext, string controllerName) { var controller1 = base.CreateController(requestContext, controllerName); var controller2 = controller1 as Controller; if (controller2 != null) controller2.ActionInvoker = new FixedAsyncRenderActionInvoker(); return controller1; } } 

创建一个umbraco启动处理程序并用上面的自定义部分替换必要的部分:

 public class UmbracoStartupHandler : ApplicationEventHandler { protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) { DefaultRenderMvcControllerResolver.Current.SetDefaultControllerType(typeof(FixedAsyncRenderMvcController)); FilteredControllerFactoriesResolver.Current.RemoveType(); FilteredControllerFactoriesResolver.Current.AddType(); base.ApplicationStarting(umbracoApplication, applicationContext); } }