2016-08-31 21 views
0

私は現在、MVCプロジェクトで次のActionFilterAttributeを持っています。最初の要求はうまく動作しますが、後続の要求はDbContextが配置されたというメッセージを返します。MVC ActionFilterAttribute DbContext Disposed Solutions

public class PermissionFilter : ActionFilterAttribute 
{ 
    private readonly ApplicationGroupManager _groupManager = new ApplicationGroupManager(); 
    private readonly ActionPermissionManager _permissionManager = new ActionPermissionManager(); 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     var request = filterContext.HttpContext.Request; 
     var response = filterContext.HttpContext.Response; 
     if (request.IsAjaxRequest()) 
     { 
      #region Preventing caching of ajax request in IE browser 

      response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1)); 
      response.Cache.SetValidUntilExpires(false); 
      response.Cache.SetCacheability(HttpCacheability.NoCache); 
      response.Cache.SetNoStore(); 

      #endregion Preventing caching of ajax request in IE browser 
     } 
     var currentAreaName = filterContext.RequestContext.RouteData.DataTokens["area"]; 
     var currentActionName = filterContext.ActionDescriptor.ActionName; 
     var currentControllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName; 
     var userId = HttpContext.Current.User.Identity.GetUserId<int>(); 

     if (!_groupManager.UserHasAdministratorAccess(userId)) 
     { 
      if (!_permissionManager.HasPermission((currentAreaName == null ? String.Empty : currentAreaName.ToString()), currentControllerName, currentActionName, userId)) 
      { 
       filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary { { "controller", "Account" }, { "action", "Login" } }); 
      } 
     } 

     base.OnActionExecuting(filterContext); 
    } 
} 

私はこれはMVC3

で導入された次の変更

重大な変更の問題であると認識十分に読んだ:ASP.NET MVC、アクションフィルタ の以前のバージョンで作成されていますいくつかの場合を除いてリクエストごとに。この動作は決して の動作を保証するものではありませんでしたが、実装の詳細と単に フィルタの契約ではステートレスであるとみなされました。 ASP.NET MVC 3では、 フィルタがより積極的にキャッシュされます。したがって、不適切なインスタンス状態を格納する任意のカスタムアクション フィルタが壊れている可能性があります。

私はこの問題を解決する最善の方法がわかりませんよ。私は2つのプライベートな読み取り専用フィールドをOnActionExecutingピースに移動して問題を解決すると考えましたが、マルチスレッドとその実装に問題があるかどうか心配です。

Castle WindsorまたはNinjectを使用してこの問題を回避している人は多いようですが、それは私の専門知識の範囲外で、Windsorチュートリアル(https://github.com/castleproject/Windsor/blob/master/docs/mvc-tutorial-intro.md)を経ても正確に何をする必要があるのか​​理解できません。

+1

Castle Windsorを使用している場合、またはNinjectはThorのハンマーでピンを叩くようなものです。 –

答えて

0

問題は、初期化しておくあなたの2つのフィールドである:

private readonly ApplicationGroupManager _groupManager = new ApplicationGroupManager(); 
private readonly ActionPermissionManager _permissionManager = new ActionPermissionManager(); 

おそらくこれらの少なくとも一つもコンストラクタやフィールド/プロパティの初期化子で初期化されているDbContextインスタンスを持っています。私は明らかにこれらのクラスの内部動作を知らないが、他の方法で使用されているようには見えない。クラスフィールドではなくメソッド内で実際に宣言する必要があります。

public override void OnActionExecuting(ActionExecutingContext filterContext) 
{ 
    ApplicationGroupManager groupManager = new ApplicationGroupManager(); 
    ActionPermissionManager permissionManager = new ActionPermissionManager(); 

    // The rest of your code here 
} 

これも表示されるエラーを修正します。 Managerインスタンス(およびそのDbContextメンバ)はリクエストごとに再初期化されるため、破棄されたインスタンスを再利用しようとするコードについて心配する必要はありません。

+0

これは私が私の質問で言ったように私が傾けている解決策です。しかし、装飾されたメソッドごとにActionFilterAttributeのインスタンスが1つしかないので、変数についての懸念はありますか?同じメソッドに対する2つの同時リクエストがこれらの変数に問題を引き起こす可能性がありますか? – Brad

+0

それは本当にあなたのための質問です。彼らはあなたのクラスです。内部的に静的または大域的な状態を保持している場合は、それが問題になる可能性があります。クラスがうまく設計され、明示的に依存関係を宣言している限り、何の問題もないはずです。 –

0

代替案は、実際のフィルタをインスタンス化し、配線するプロキシ・フィルタ・クラスを作成することです。

PermissionFilterの代わりに、このプロキシを設定(追加)します。

+0

これは面白い解決策です...ありがとう。 – Brad

+0

これは依然として、リクエストごとにマネージャクラスを再初期化することに注意してください。以下の私のソリューションと効果的に同じ効果がありますが、基本的なフィルタを変更できない場合(または何らかの理由で本当にしたくない場合)には、このソリューションが優れています。 –

関連する問題