0

사용자 인증의 몇 가지 측면을 처리하기 위해 사용자 정의 AuthorizeAttribute을 사용합니다. 권한 부여 중에 값을 확인하려면 데이터베이스에 대한 액세스 권한을 추가해야합니다. 이 프로젝트는 Repository 패턴을 사용하고 Repos는 모두 StructureMap을 통해 컨트롤러 생성자에서 인스턴스화됩니다.ASP.NET의 StructureMap에서 설정 기 주입이 작동하지 않습니다. MVC 인증 필터

불행히도 필터가있는 생성자 삽입을 사용할 방법이 없다고합니다. Jimmy Bogard (http://lostechies.com/jimmybogard/2010/05/03/dependency-injection-in-asp-net-mvc-filters/)가이 시나리오를 처리하기 위해 속성 주입을 사용하는 방법을 설명하는 기사를 발견했습니다. 기본적으로 지미의 코드는 ControllerActionInvokerGetFilters 메서드를 가로 채고 각 필터에서 BuildUp을 실행하여 속성을 채 웁니다. 이것은 내가 필요로했던 단지, 그래서 나는 다음 클래스 추가 -

public class InjectingActionInvoker : ControllerActionInvoker 
{ 
    private readonly IContainer _container; 

    public InjectingActionInvoker(IContainer container) 
    { 
     _container = container; 
    } 

    protected override FilterInfo GetFilters(
     ControllerContext controllerContext, 
     ActionDescriptor actionDescriptor) 
    { 
     var info = base.GetFilters(controllerContext, actionDescriptor); 

     info.AuthorizationFilters.ForEach(_container.BuildUp); 
     info.ActionFilters.ForEach(_container.BuildUp); 
     info.ResultFilters.ForEach(_container.BuildUp); 
     info.ExceptionFilters.ForEach(_container.BuildUp); 

     return info; 
    } 
} 

을 그리고이 라인 StructureMap로 유선 -

For<IActionInvoker>().Use<InjectingActionInvoker>(); 
For<ITempDataProvider>().Use<SessionStateTempDataProvider>(); 

Policies.SetAllProperties(c => 
{ 
    c.OfType<IActionInvoker>(); 
    c.OfType<ITempDataProvider>(); 
    c.WithAnyTypeFromNamespaceContainingType<UserProfileRepository>(); 
}); 

그리고 마지막으로, 나는 내 사용자 지정 AuthorizeAttribute에 공유 재산을 추가 클래스 -

[SetterProperty] 
public UserProfileRepository User { get; set; } 

내가 프로젝트를 실행하고 보안 페이지에 액세스, 일 e AuthorizeCore 코드가 두 번 눌립니다. 처음으로, 내 재산이 설정되어 제대로 작동합니다. 그러나 속성이 null이기 때문에 두 번째 호출이 실패합니다. GetFilters 메서드에서 중단 점을 설정하고 처음으로 만 실행됩니다. 불행하게도, 나는 이것이 구조적으로 멀리 떨어져있는 곳을 정확히 알기 위해 StructureMap이나 필터를 충분히 이해하지 못했습니다.

다음은 누군가를 위해 유용이 경우, 호출 스택입니다 -

전화 번호 1

AppName.dll!AppName.Filters.SiteAuthorizeAttribute.AuthorizeCore(System.Web.HttpContextBase httpContext) Line 78 C# 
[External Code] 
AppName.dll!AppName.Filters.SiteAuthorizeAttribute.OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext) Line 31 C# 
[External Code] 

전화 번호 2

AppName.dll!AppName.Filters.SiteAuthorizeAttribute.AuthorizeCore(System.Web.HttpContextBase httpContext) Line 69 C# 
[External Code] 
AppName.dll!AppName.Filters.SiteAuthorizeAttribute.OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext) Line 31 C# 
[External Code] 
App_Web_1fnmflat.dll!ASP._Page_Views_Shared__Menu_cshtml.Execute() Line 2 C# 
[External Code] 
App_Web_1fnmflat.dll!ASP._Page_Views_Shared__Layout_cshtml.Execute() Line 51 C# 
[External Code] 

모든 StructureMap 주인이 어떤 지혜를 공유하는 걱정 ? 어떤 도움을 주셔서 미리 감사드립니다!

편집 : 여기에 _Menu.cshtml 파일에 대한 코드입니다 -

@(Html.Kendo().Menu() 
     .Name("Menu") 
     .Items(items => 
     { 
      items.Add().Text("My Dashboard").Action("Dashboard", "Home"); 
      items.Add().Text("My Account").Action("Edit", "Account"); 
      items.Add().Text("Purchase/Renew").Action("Index", "Purchase"); 
      items.Add().Text("Administration") 
       .Items(children => 
       { 
        children.Add().Text("Accounts").Action("Index", "UserProfile"); 
        children.Add().Text("Coupons").Action("Index", "Coupon"); 
       }); 
      items.Add().Text("Logout").Action("Logout", "Logon"); 
     }) 
    ) 

감사 NightOwl888에서하라는 일부는 내가 검도 메뉴 호출에 문제를 격리 한에가. _Menu.cshtml의 마지막 줄에 중단 점을 놓고 들어가면 DoGetInstance가 내 HomeController에 호출됩니다. 완료되면 OnAuthorization이 두 번째로 실행되고 repo 속성은 null입니다.

누구나 내가 여기에서 무엇을 놓치고 있는지 알고 있습니까?

+0

을 나는 당신이 당신의 권한 부여 속성이 두 번 호출되는 이유를 설명하지 않는 한 당신이 답을 찾을 수 있다고 생각하지 않으며, 사람은 두 번째 인스턴스화. GetFilters 메서드가 두 번 호출되고 있습니까? – NightOwl888

+0

죄송합니다. 두 번째 호출은 _Layout.cshtml 파일에서 _Menu.cshtml이라는 이름의 부분 렌더링에서 발생합니다 (호출 스택에서이를 볼 수 있음). –

+0

그리고 GetFilters는 위에서 설명한 것처럼 한 번만 호출됩니다. 클래스가 캐시되고있는 것처럼 느껴지지만 BuildUp이 발생하기 전에 캐시 된 버전이 저장되고 있습니까? 나는 모른다. –

답변

0

전에 슬프게도, 나는 무슨 일이 일어나고 있는지 추적 할 수 없었다. 그래서 여기 내가 지금이 문제를 "해결"한 방법 -

[SetterProperty] 
    public UserProfileRepository User 
    { 
     get { return _user ?? DependencyResolver.Current.GetService<UserProfileRepository>(); } 
     set { _user = value; } 
    } 

을 주입은 주입 된 값을 사용 작동 할 때, 그렇지 않으면 내가 손으로 더러운 일을하기 위해 DependencyResolver를 사용합니다. 예쁘지는 않지만 지금은 다른 옵션이 없습니다.

나는이 스레드에 설명 된대로이, 사용자 정의 필터 제공 업체와 일을하지 않았다
0

두 번째 호출 중에 GetFilters가 호출되지 않고, AuthorizeAttribute의 첫 번째 인스턴스가 작동 중이라는 것을 알고 있기 때문에 이것은 DI 설정에서 분명히 문제가되지 않습니다. AuthorizeAttribute 인스턴스가 캐시 된 경우 모든 종속성도 캐시되므로 해당 인스턴스도 캐시되지 않습니다.

이 문제는 사용자의 메뉴가 AuthorizeAttribute를 사용하기 전에 FilterProviders.Providers.GetFilters(controllerContext, actionDescriptor); 메서드를 호출하지 않는다는 사실로 귀결됩니다. 나는 당신이 당신의 메뉴 나 그 부분적인 메소드를위한 코드를 제공하지 않았기 때문에 왜 그런지에 대해서만 추측 할 수있다.

대신 ControllerActionInvoker.InvokeAuthorizationFilters을 무시할 수 있습니다.

+0

감사. InvokeAuthorizationFilters를 시도했지만 같은 결과가 나타납니다. 위 편집에서 자세한 내용을 추가했습니다. –

0

나는 똑같은 문제에 직면했고 다른 방법을 시도했다. 마침내 이것은 [AllowMultiple = true]을 제거한 후 나를 위해 일했고 지금은 AuthorizeCore이 한 번 호출된다. 이것이 AuthorizeCore에 어떻게 링크되어 있는지 궁금합니다.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] 
public class CompanyAuthorizeAttribute : AuthorizeAttribute 
{} 

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] 
public class CompanyAuthorizeAttribute : AuthorizeAttribute 
{} 
+0

고마워, 모한. Unfortuantely 당신의 수정 프로그램이 나를 위해 작동하지 않았다. 다행히도이 페이지를 비틀 거리는 다른 누군가를 위해! –

+0

내가 틀렸어. MVC5 proj에서 작업 중이었고 StructureMap.MVC5 @GitHub를 설치했습니다. 이것은 기본 IOC를 제공합니다. IOC for Filters를 구현하기 위해 아래 수정을했습니다. ActionInvoker는 컨테이너 obj를 기대합니다. public static IContainer Initialize() { \t var _con = 새 컨테이너 (c => c.AddRegistry ()); \t _con.Configure (c => c.AddRegistry (새 ActionFilterRegistry (_con))); \t return _con; } 공용 클래스 ActionFilterRegistry : 레지스트리 { \t 공공 ActionFilterRegistry (IContainer를 콘)에 대한 \t { \t \t ()를 사용 (새 InjectingActionInvoker (사기꾼)). \t \t Policies.SetAllProperties (....); \t} } –

0

: I 옵션의 무리를했지만, 내 속성으로 기능을 해결 종속성을 주입 결국

How can you unit test an Action Filter in ASP.NET Web Api?

. 그런 식으로 유닛 테스트는 가짜, 모의 또는 무엇이든 반환하는 함수를 삽입 할 수 있지만 응용 프로그램은 IoC 컨테이너를 사용하여 종속성을 해결하는 함수를 삽입 할 수 있습니다.

내가 어떻게 작동하는지에 대한 간단한 블로그 게시물을 작성했습니다. 당신이 어떻게 생각하는지 듣고 사랑하고 당신을 도와하면 다음과 같습니다

http://danielsaidi.com/blog/2015/09/11/asp-net-and-webapi-attributes-with-structuremap