5

リクエストごとにクラウドデータベースからユーザーをロードし、asp.net mvc を使用してコントローラーでリクエストで利用できるようにしたいと考えています。問題は、現在のフレームワークがアクション フィルターからの非同期操作の実行をサポートしていないことです。したがって、OnActionExecuting、OnAuthorization メソッドではこれを行うことができません..たとえば、次のコードは機能しません (試してはいけません)。例外が発生します:「非同期モジュールまたはハンドラーが非同期処理中に完了しました。操作はまだ保留中です。」

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);
}

私はおそらくそこでそれをすることができますか?

4

1 に答える 1

10

質問は3か月前なので、これを回避できたと思います。とにかく、私は同じようなことをしなければならなかったので、ここに私の解決策を追加します。

ParallelExtensionsExtrasライブラリのToAsyncメソッドを使用しました。これは私のクラスです:

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);
    }
}

TaskとIAsyncResult間の変換については、Microsoftのこのドキュメントも参照してください。

于 2013-01-26T13:37:51.803 に答える