2016-08-31 2 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에서는 필터가보다 적극적으로 캐시됩니다. 따라서 인스턴스 상태를 부적절하게 저장하는 모든 사용자 지정 동작 필터가 손상 될 수 있습니다.

이 문제를 해결하는 가장 좋은 방법이 확실하지 않습니다. 두 개의 개인 읽기 전용 필드를 OnActionExecuting 조각으로 이동하여이 문제를 해결할 수 있다고 생각했지만 멀티 스레딩과 해당 구현에 문제가 있을지 걱정됩니다.

캐슬 윈저 (Castle Windsor) 나 닌젝트 (Ninject)를 사용하여 많은 사람들이이 문제를 해결해 왔지만 내 수준의 전문 지식을 벗어났습니다. 심지어 윈저 튜토리얼 (https://github.com/castleproject/Windsor/blob/master/docs/mvc-tutorial-intro.md)을 통과 한 후에도 정확히 무엇을해야하는지 이해할 수 없습니다.

+1

Castle Windsor 또는 Ninject를 사용하는 경우 Thor의 망치로 핀을 치려고하는 것과 같습니다. –

답변

0

문제는 당신이 초기화하고 유지하여 두 개의 필드, 함께 :

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 인스턴스 만 있기 때문에 변수에 대한 염려가 있습니까? 동일한 메소드에 대한 두 개의 동시 요청으로 인해 이러한 변수에 문제가 발생할 수 있습니까? – Brad

+0

그건 정말 당신에게 질문입니다. 그들은 당신의 수업입니다. 정적 또는 전역 상태를 내부적으로 유지한다면 예 - 이것이 문제 일 수 있습니다. 클래스가 잘 설계되고 명시 적으로 종속성을 선언하는 한 아무 문제가 없어야합니다. –

0

대안은 실제 필터를 인스턴스화하고 연결하는 프록시 필터 클래스를 만드는 것입니다.

PermissionFilter 대신이 프록시를 지금 구성 (추가)합니다.

+0

이것은 흥미로운 해결책입니다 ... 감사합니다. – Brad

+0

여전히 요청 당 관리자 클래스를 다시 초기화해야합니다.아래의 솔루션과 효과적으로 동일하지만, 기본 필터를 수정할 수 없거나 어떤 이유로 든 정말로 원하지 않는 경우이 솔루션이 더 좋습니다. –

관련 문제