2016-11-15 6 views
4

asp.netコアアプリケーションにミドルウェアをセットアップして、コントローラーのアクションをトランザクション内で自動的にラップします。コントローラーからミドルウェアに情報を渡す

public async Task Invoke(HttpContext context, MyDataContext dbContext) 
{ 
    if (context.Request.Method == "GET") 
    { 
     await _next(context); 
    } 
    else 
    { 
     using (var transaction = await dbContext.Database.BeginTransactionAsync()) 
     { 
      try 
      { 
       await _next(context); 
       transaction.Commit(); 
      } 
      catch (Exception) 
      { 
       transaction.Rollback(); 
       throw; 
      } 
     } 
    } 
} 

しかし、トランザクションでは実行しないでください(将来的にはこれ以上)コントローラメソッドが1つあります。コントローラのアクションをミドルウェア機能の「オプトアウト」にする最良の方法は何でしょうか?

[NoTransaction]のようなカスタム属性をコントローラメソッドに配置するとよいでしょう。しかし、私はミドルウェアのInvoke()メソッドから正確にコントローラアクションが呼び出される(これにより、そのメソッドから属性を引き出して、作成するかどうかを決定することができます)トランザクション)これを行う正しい方法は何でしょうか?

答えて

1

あなたが探しているのはカスタムフィルターだと思います。

ActionFilterAttributeから派生した新しいクラスを作成できます。 次に、OnActionExecutingメソッドとOnActionExecutedメソッドをオーバーライドして、トランザクション処理を追加できます。

次に、属性を使用してフィルタを実行するメソッドに追加することができます。クラス "CustomFilterAttribute"に名前を付けた場合は[CustomFilter]です。

フィルタクラスの有効期間をさらに制御する必要がある場合は、ActionFilterをServiceFilterとして使用できます。それをサービスとして登録する必要があり、依存関係注入を使用することもできます。 ServiceFilter属性は多少異なって見える:

[ServiceFilter(typeof(CustomFilter))] 

このために良いの参照です: https://damienbod.com/2015/09/15/asp-net-5-action-filters/

+0

これは面白い聞こえるが、私は提案を理解していない - これは私がシステム全体のトランザクションを持つことができません既定でコントローラのアクションを行い、属性を使用してオプトアウトしますか? –

+0

私の提案するソリューションは、オプトインアプローチを採用し、フィルタコード内でトランザクション処理を行う方が適しています。 オプトアウトについては、提供されたリンクの「グローバルフィルタとしてのフィルタの使用」を参照してください。基本的にすべてのコントローラにデフォルトフィルタを適用できます。 これで、トランザクションを作成するかどうかを指定し、トランザクションを作成しない場所に属性を手動で追加するかどうかを指定するブール値をパラメータとして追加できます。 – FelschR

+0

ActionFilterのメソッドはメソッドの始めと終わりに呼び出されるので、トランザクションをクラスのメンバにする必要があります。 transaction.Dispose();を呼び出してください。 – FelschR

関連する問題