I'm using my custom authorization filter as it's here How do you create a custom AuthorizeAttribute in ASP.NET Core? but in run time get this error: "InvalidOperationException: A suitable constructor for type 'papillon.Common.RoleRequirementFilter' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.'. " Should I change some code in my startup.cs ?!?!
this is my AuthorizationFilter
public class RoleRequirementFilter : IAuthorizationFilter
{
private readonly string[] _rolesNames;
public RoleRequirementFilter(string[] roleNames)
{
_rolesNames = roleNames;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
if (context.HttpContext.User.IsInRole("Support"))
return;
foreach (var item in _rolesNames)
if (context.HttpContext.User.IsInRole(item))
return;
context.Result = new ForbidResult();
// context.Result = new UnauthorizedResult();
}
}
this is my TypeFilterAttribute
public class RoleRequirementAttribute : TypeFilterAttribute
{
public RoleRequirementAttribute(string[] roleNames) : base(typeof(RoleRequirementFilter))
{
Arguments = roleNames;
}
}
this is my startup.cs
services.AddControllersWithViews().AddRazorRuntimeCompilation();
// ...
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}").RequireAuthorization();
endpoints.MapRazorPages().RequireAuthorization();
});
and this is how I use it in my controller
[RoleRequirement(roleNames:new string[]{Roles.Admin1, Roles.Admin2, Roles.Center1})]
CodePudding user response:
TypeFilterAttribute.Arguments
is the array of objects that will be passed to the constructor of the filter you are constructing. Your filter has a single constructor parameter roleNames
which happens to be a string array. But by setting Arguments = roleNames
you are effectively telling the framework to pass each role name as an individual argument to the filter’s constructor. But since your filter does not have a variable number of string parameters (but just a single string array parameter), this will not match up.
So instead, you should adjust your type filter to pass the string array itself as the sole argument to your filter:
public class RoleRequirementAttribute : TypeFilterAttribute
{
public RoleRequirementAttribute(string[] roleNames) : base(typeof(RoleRequirementFilter))
{
Arguments = new object[] { roleNames };
}
}
CodePudding user response:
you can define your roles as enum, then use ResultFilterAttribute in order to accept any inRole Users like this:
public class UserAuthorization : ResultFilterAttribute
{
RolesEnum[] _roles;
public UserAuthorization(RolesEnum[] roles)
{
_roles = roles;
}
public override void OnResultExecuting(ResultExecutingContext context)
{
// if not in role throw exception
base.OnResultExecuting(context);
}
}
in above any controller you can use this attribute like this:
[UserAuthorization(new RolesEnum[] { RolesEnum.Admin1, RolesEnum.Branch1,RolesEnum.Center1 })]
public class MyController : Controller