2012-10-18 92 views
5

我希望能夠在每個請求上從雲數據庫加載用戶,並使用asp.net mvc在控制器中的請求上提供該請求。問題是當前框架不支持從動作過濾器中執行異步操作。所以OnActionExecuting,OnAuthorization方法不允許我這樣做..例如我有下面的代碼不工作(所以不要嘗試它)..你會得到一個異常:「異步模塊或處理程序完成,而異步手術仍在進行中。「在操作之外執行異步操作asp.net mvc

protected async override void OnAuthorization(AuthorizationContext filterContext) 
{ 
    var user = filterContext.HttpContext.User; 
    if (!user.Identity.IsAuthenticated) 
    { 
    HandleUnauthorizedRequest(filterContext); 
    return; 
    } 

    using (var session = MvcApplication.DocumentStore.OpenAsyncSession()) 
    { 
    User currentUser = await session.LoadAsync<User>(user.Identity.Name); 
    if (currentUser == null) 
    { 
     HandleUnauthorizedRequest(filterContext); 
     return; 
    } 

    filterContext.HttpContext.Items["User"] = currentUser; 
    } 
} 

那麼有沒有其他的方法可以做到這一點?我注意到在基本控制器中有一個開始執行方法:

protected override IAsyncResult BeginExecute(RequestContext requestContext, AsyncCallback callback, object state) 
{ 
    return base.BeginExecute(requestContext, callback, state); 
} 

我可以這樣做嗎?

+0

您可以[在此投票支持異步操作過濾器](https://aspnet.codeplex.com/workitem/9582)。 –

+0

我最近[發佈了一個庫](https://www.nuget.org/packages/Hydrogen.Extensions.Mvc5.Async),它增加了對異步過濾器的適當支持(主要基於[ASP.NET MVC芯(https://github.com/aspnet/Mvc))。 源也可在這裏:https://github.com/jdaigle/Hydrogen.Extensions.Mvc5。 –

回答

10

問題是三個月大,所以我想你已經設法解決這個問題。無論如何,我會在這裏添加我的解決方案,因爲我不得不做類似的事情。

我使用了ParallelExtensionsExtras庫中的一些方法。這是我的課程:

public class AsyncControllerBase : Controller 
{ 
    protected override IAsyncResult BeginExecute(System.Web.Routing.RequestContext requestContext, AsyncCallback callback, object state) 
    { 
     return ExecuteCoreAsync(requestContext, state).ToAsync(callback, state); 
    } 

    protected override void EndExecute(IAsyncResult asyncResult) 
    { 
     IAsyncResult baseAsyncResult = ((Task<IAsyncResult>)asyncResult).Result; 
     base.EndExecute(baseAsyncResult); 
    } 

    protected virtual async Task<IAsyncResult> ExecuteCoreAsync(System.Web.Routing.RequestContext requestContext, object state) 
    { 
     await DoStuffHereOrInDerivedClassAsync(); 

     var baseBeginExecuteCompletion = new TaskCompletionSource<IAsyncResult>(); 

     AsyncCallback callback = ar => 
     { 
      baseBeginExecuteCompletion.SetResult(ar); 
     }; 

     // OnActionExecuting will be called at this point 
     var baseAsyncResult = base.BeginExecute(requestContext, callback, state); 

     await baseBeginExecuteCompletion.Task; 

     return baseAsyncResult; 
    } 

    protected override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     base.OnActionExecuting(filterContext); 
    } 
} 
+1

請注意''Controller.Request'和其他許多屬性在'DoStuffHereOrInDerivedClassAsync()'內部是'null',最好通過'RequestContext'作爲參數來訪問某些特性。 – deerchao

+0

爲什麼OnActionExecuting的'空'覆蓋? –

+0

嗨德克,我寫這篇文章已經兩年半了,所以我實在不記得:)也許最初的目的是爲了避免混淆派生類中的覆蓋 - 但忘記了實際上它?! –