1

ユースケースは単純です。_Layout.cshtml には、ログインしているユーザーの情報が表示されます。その情報は毎回更新する必要があります。

私はそれを行う2つの方法を見つけました

  • 後で _Layout.cshtml で使用されるメソッド セットに と がありBaseControllerますOnActionExecutingViewBag.UserInfo = ...;
  • _Layout.cshtmlで_@{Html.RenderAction("GlobalUserInfo", "UserInfo");}

問題は、非同期メソッドから UserInfo が返された場合、これら 2 つの方法がデッドロックまたは例外で惨めに失敗することpublic async Task<UserInfo>GetUserInfo(){...}です。

問題はこれです: async/await を使用してデータを取得するときに、すべてのアクションで ViewBag プロパティを設定する方法。

4

1 に答える 1

2

MVC はasync、特にフィルターを使用する場合、完全にフレンドリーというわけではありません。

独自のRenderAsyncAction拡張メソッドを作成するか、すべてのasyncアクションでコードを複製できます。

または、ちょっとしたハックを試みることもできます。ASP.NET で使用するとデッドロックが発生する理由をResultブログで説明していますが、回避策があります: use ConfigureAwait(false)on every await in GetUserInfo.

次に、同期ラッパーを定義できます。

public UserInfo GetUserInfoBlocking()
{
  return GetUserInfo().Result;
}

またはGetUserInfoBlockingで使用できるはずです。OnActionExecutingRenderAction

副作用に注意してください:

  • このアプローチでは、リクエストごとに複数のスレッドが使用されるため、スケーラビリティが低下します。純粋なasyncアプローチでは、スレッドごとに複数のリクエストが使用されるため、スケーラビリティが向上します。
  • からの例外はすべてGetUserInfoでラップされるAggregateExceptionため、ログに詳細が記録されていることを確認してください。そうしないと、InnerExceptionログに意味のないエラーが記録されます。

asyncこのようにブロックするのではなく、ずっと下まで使用するのが間違いなく最善です。しかし、MVC では選択の余地がない場合があります (これは将来変更されることを願っています)。

于 2012-12-04T13:46:02.037 に答える