I'musing ASP.NET Web API and I need to have authorization so I've created custom authorization attribute
public class CustomAuthorizationAttribute : AuthorizeAttribute
In order to inject dependency inside constructor I have following :
public CustomAuthorizationAttribute(IAccountBL accountBl)
{
_accountBL = accountBl;
}
In IAccountBL
I have method which interacts with database checking if user is authorized to make request.
Inside Member API controller I've register that attribute
[CustomAuthorization]
public class MemberController : ApiController
But I get following error
Project.Account.AccountBL' does not contain a constructor that takes 0 arguments
And if I register it like
[CustomAuthorization(IAccountBL)]
Thank you
That said, if you're intent on injecting into an attribute, you can use the ASP.NET Core MVC IApplicationModelProvider . The framework passes dependencies into the provider's constructor, and the provider can pass dependencies to the attribute's properties or methods. In your Startup, register your provider.
TypeFilterAttribute. TypeFilterAttribute is similar to ServiceFilterAttribute, but its type isn't resolved directly from the DI container. It instantiates the type by using Microsoft. Extensions.
You can create custom filter attributes by implementing an appropriate filter interface for which you want to create a custom filter and derive the FilterAttribute class to use that class as an attribute. For example, implement IExceptionFilter and the FilterAttribute class to create a custom exception filter.
Action filters are just attributes. You do not have control over when those attributes are instantiated by the CLR. One possibility 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 could use the marker attribute:
[CustomAuthorization]
public class MemberController : ApiController
{
...
}
You can get dependency in your filter by using extension method GetDependencyScope
for class HttpRequestMessage
. It's not a canonical way for dependency injection, but can be used as workaround. A basic example may 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 may be used with constructor injection 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; }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With