2012-10-18 14 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; 
    } 
} 

他にもこれを行う方法はありますか?ベースコントローラーにbegin executeメソッドがあることに気付きました。

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

可能性はありますか?

+0

[ここで非同期アクションフィルターに投票できます](https://aspnet.codeplex.com/workitem/9582)。 –

+0

私は非同期フィルタ(ASP.NET MVCのコードに大きく基づいています)を適切にサポートするライブラリを最近公開しました(https://www.nuget.org/packages/Hydrogen.Extensions.Mvc5.Async)コア](https://github.com/aspnet/Mvc))。 ソースはhttps://github.com/jdaigle/Hydrogen.Extensions.Mvc5でも利用できます。 –

答えて

10

質問は3か月間ですので、これを回避することができました。とにかく、何か似たようなことをしなければならないので、ここで私の解決策を追加します。

私は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

こんにちはダーク、私はこれを書いてから2年半が経過していますので、正直に覚えていません:)オリジナルの意図は、派生クラスの混乱を避けるためにオーバーライドを封印することでした。それ?! –

関連する問題