Custom filter attributes introduce dependency

I use ASP.NET Web API and I need to have authorization, so I created a special authorization attribute

public class CustomAuthorizationAttribute : AuthorizeAttribute 

To introduce the dependency inside the constructor, I have the following:

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

In IAccountBL I have a method that interacts with database validation if the user has the right to make a request. Inside the member API I registered this attribute

  [CustomAuthorization] public class MemberController : ApiController 

But I get the following error

Project.Account.AccountBL 'does not contain a constructor that takes 0 arguments

And if I register it as

 [CustomAuthorization(IAccountBL)] 

enter image description here

thanks

+4
source share
3 answers

If anyone finds a similar problem, how do I do it.

My custom filter inherits from IAutofacAuthorizationFilter . Apart from this, you can also inherit IAutofacExceptionFilter and IAutofacActionFilter . And inside my DI container, I registered this filter for each controller that I want to use, like this

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

Action filters are just attributes. You have no control over when these attributes are created by the CLR. One option is to write a marker attribute:

 public class CustomAuthorizationAttribute : Attribute { } 

and then the actual action filter:

 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 } } } 

and finally register it as a global action filter:

 public static class WebApiConfig { public static void Register(HttpConfiguration config) { ... IAccountBL accountBL = ... config.Filters.Add(new CustomAuthorizationFilter(accountBL)); } } 

and finally you can use the marker attribute:

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

You can get the dependency in your filter using the GetDependencyScope extension GetDependencyScope for the HttpRequestMessage . This is not a canonical path for dependency injection, but can be used as a workaround. A basic example might look like this:

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

This method can be used with the constructor injector to simplify unit testing:

 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; } } 
+4
source

Source: https://habr.com/ru/post/1498633/


All Articles