I'm trying to pass arguments to an IAsyncAuthorizationFilter
filter from the TypeFilterAttribute
. I made a simple example which according to answers such as this one https://stackoverflow.com/a/44435070/937131 should work.
public class SimpleAuthorizeServiceAttribute : TypeFilterAttribute
{
public SimpleAuthorizeServiceAttribute(string service, string context, AccessType access) : base(typeof(SimpleAuthorizeServiceAttribute))
{
Arguments = new[] { new PermissionData(service, context, access) };
}
public class SimpleAuthorizeServiceFilter : IAsyncAuthorizationFilter
{
private readonly PermissionData _permissionData;
public SimpleAuthorizeServiceFilter(PermissionData permissionData)
{
_permissionData = permissionData;
}
public virtual Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
var test = _permissionData.Service != null;
return Task.CompletedTask;
}
}
}
I've then applied this to a method like this:
[HttpGet]
[SimpleAuthorizeService("test-service", "test-context", AccessType.Read)]
public async Task<bool> ServiceTest()
{
bool isAllowed = this.HttpContext.IsUserAllowedToAccess(10, 20, 30);
return isAllowed;
}
Which fails with
System.InvalidOperationException: A suitable constructor for type 'SecurityAttribute.Application.ServiceToServiceAttribute.SimpleAuthorizeServiceAttribute' could not be located. Ensure the type is concrete and all parameters of a public constructor are either registered as services or passed as arguments. Also ensure no extraneous arguments are provided.
I thought this might be because I'm not using params
for the TypeFilterAttribute
(which is dumb). So i rewrote it to this monstrosity..
public class SimpleAuthorizeServiceAttribute : TypeFilterAttribute
{
public SimpleAuthorizeServiceAttribute(params string[] data) : base(typeof(SimpleAuthorizeServiceAttribute))
{
// hoorray for non type safe paramaters...
var success = AccessType.TryParse(data[2], out AccessType access);
Arguments = new[] { new PermissionData(data[0], data[1], access) };
}
public class SimpleAuthorizeServiceFilter : IAsyncAuthorizationFilter
{
private readonly PermissionData _permissionData;
public SimpleAuthorizeServiceFilter(PermissionData permissionData)
{
_permissionData = permissionData;
}
public virtual Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
var test = _permissionData.Service != null;
return Task.CompletedTask;
}
}
}
....
[HttpGet]
[SimpleAuthorizeService("test-service", "test-context", "Read")]
public async Task<bool> ServiceTest()
{
bool isAllowed = this.HttpContext.IsUserAllowedToAccess(10, 20, 30);
return isAllowed;
}
But that still trows an error:
System.InvalidOperationException: A suitable constructor for type 'SecurityAttribute.Application.ServiceToServiceAttribute.SimpleAuthorizeServiceAttribute' could not be located. Ensure the type is concrete and all parameters of a public constructor are either registered as services or passed as arguments. Also ensure no extraneous arguments are provided. at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.FindApplicableConstructor(Type instanceType, Type[] argumentTypes, ConstructorInfo& matchingConstructor, Nullable`1[]& matchingParameterMap)
So how is one supposed to pass arguments to a IAsyncAuthorizationFilter
?
CodePudding user response:
The issue is with this line
public SimpleAuthorizeServiceAttribute(string service, string context, AccessType access) :
base(typeof(SimpleAuthorizeServiceAttribute)) // problem is here
{
Arguments = new[] { new PermissionData(service, context, access) };
}
it should be SimpleAuthorizeServiceFilter not SimpleAuthorizeServiceAttribute.
replace it and it should work.