2013-08-23 70 views
4

I'musing的ASP.NET Web API,我需要获得授权,所以我已经创建自定义授权属性自定义过滤器的属性注入依赖

public class CustomAuthorizationAttribute : AuthorizeAttribute 

为了注入内部构造依赖我有以下几点:

 public CustomAuthorizationAttribute(IAccountBL accountBl) 
    { 
     _accountBL = accountBl; 
    } 

IAccountBL我有方法与数据库检查交互如果用户被授权发出请求。 内部会员API控制器我已经注册该属性

[CustomAuthorization] 
public class MemberController : ApiController 

,但我得到以下错误

Project.Account.AccountBL”不包含一个构造函数参数0

如果我注册它就像

[CustomAuthorization(IAccountBL)] 

enter image description here

谢谢

+1

这可能帮助:http://stackoverflow.com/questions/6193414/依赖注入与ninject和过滤器属性的asp网络mvc –

回答

1

如果有人发现类似的问题,这是我如何设法解决它。

我的自定义过滤器继承IAutofacAuthorizationFilter。除此之外,您还可以继承IAutofacExceptionFilterIAutofacActionFilter。 我的DI容器内我已经注册该过滤器为每个控制器我想用这样的

 builder.Register(c => new CustomAuthorizationAttribute(c.Resolve<IAccountBL>())) 
       .AsWebApiAuthorizationFilterFor<MemberController>() 
       .InstancePerApiRequest(); 
8

行动过滤器只是属性。您无法控制CLR实例化这些属性的时间。一种可能性是写一个标记属性:

public class CustomAuthorizationAttribute : Attribute { } 

,然后实际操作筛选:

public class CustomAuthorizationFilter : ActionFilterAttribute 
{ 
    private readonly IAccountBL accountBL; 
    public CustomAuthorizationFilter(IAccountBL accountBL) 
    { 
     this.accountBL = accountBL; 
    } 

    public override void OnActionExecuting(HttpActionContext actionContext) 
    { 
     if (actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<CustomAuthorizationAttribute>().Any() || 
      actionContext.ActionDescriptor.GetCustomAttributes<CustomAuthorizationAttribute>().Any()) 
     { 
      // here you know that the controller or action is decorated 
      // with the marker attribute so that you could put your code 
     } 
    } 
} 

,并最终把它注册为一个全球性的动作过滤器:

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 
     ... 

     IAccountBL accountBL = ... 
     config.Filters.Add(new CustomAuthorizationFilter(accountBL)); 
    } 
} 

最后你可以使用标记属性:

[CustomAuthorization] 
public class MemberController : ApiController 
{ 
    ... 
} 
+0

我为我的无知道歉,请你解释我这部分 'IAccountBL accountBL = ...'因为我正在注入对AccountBL的依赖?初始化如何进行? – jasenkoh

+0

您可以从DI容器中检索它。 –

+0

我刚开始使用DI,这对我来说是全新的世界。你能帮我吗,我如何从DI容器中取回它?我有注册模块,过滤器和控制器的AutoFacDependencyResolver类。 – jasenkoh

4

您可以通过使用扩展方法GetDependencyScopeHttpRequestMessage类让你的过滤器的依赖。这不是依赖注入的规范方式,但可以用作解决方法。一个基本的例子可能是这样的:

public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken) 
    { 
     var dependencyScope = context.Request.GetDependencyScope(); 
     var dependency = dependencyScope.GetService(typeof (MyDependencyType)); 
     //use your dependency here 
    } 

这种方法可以与构造器注入来简化单元测试:

public class MyAuthenticationFilter : Attribute, IAuthenticationFilter 
{ 
    private Func<HttpRequestMessage, MyDependencyType> _dependencyFactory; 

    public MyAuthenticationFilter() : 
     this(request => (MyDependencyType)request.GetDependencyScope().GetService(typeof(MyDependencyType))) 
    { 
    } 

    public MyAuthenticationFilter(Func<HttpRequestMessage, MyDependencyType> dependencyFactory) 
    { 
     _dependencyFactory = dependencyFactory; 
    } 

    public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken) 
    { 
     var dependencyScope = context.Request.GetDependencyScope(); 
     var dependency = dependencyFactory.Invoke(context.Request); 
     //use your dependency here 
    } 

    public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken) 
    { 
     throw new NotImplementedException(); 
    } 

    public bool AllowMultiple { get; private set; } 
}