I'm using ASP.NET Core identity
and I want to observe DIP and I create a interface
public interface IUserManagerService : IDisposable
{
Task<IdentityResult> CreateAsync(User user, string password);
}
and implementation class is
public class UserManagerService : UserManager<User>, IUserManagerService
{
public UserManagerService()
: base()
{
}
}
now I don't know what parameters should pass to base class
how can I fix that ?
From your description, you want to create a service with the UserManager, then use it to manage users. If that is the case, you could refer the following sample code:
public interface IUserManagerService:IDisposable
{
Task<IdentityResult> CreateAsync(User user, string password);
}
public class UserManagerService : IUserManagerService
{
//request the UserManger service and call the relate methods.
private readonly UserManager<IdentityUser> usermanager;
public UserManagerService(UserManager<IdentityUser> userManager)
{
usermanager = userManager;
}
public async Task<IdentityResult> CreateAsync(User user, string password)
{
var identityuser = new IdentityUser { UserName = user.UserName, Email = user.Email };
var result = await usermanager.CreateAsync(identityuser, password);
return result;
}
public void Dispose()
{
Console.WriteLine("- IUserManagerService was disposed!");
}
}
The User model:
public class User
{
public string UserName { get; set; }
public string Email { get; set; }
}
Then, registers the IUserManagerService service with the concrete type UserManagerService:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDatabaseDeveloperPageExceptionFilter();
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddControllersWithViews();
services.AddScoped<IUserManagerService, UserManagerService>();
Then, in the MVC controller, request the IUserManagerService service, and call its method to create a user:
public class HomeController : Controller
{
private readonly IUserManagerService userManagerService;
public HomeController(IUserManagerService userManager)
{
userManagerService = userManager;
}
public IActionResult Index()
{
var newuser = new User() { UserName = "Tom", Email = "tom121#hotmail.com" };
var password = "Password123!";
var result = userManagerService.CreateAsync(newuser, password);
if (result.Result.Succeeded)
{
//do some thing
}
return View();
}
The result as below:
More detail information, refer Dependency injection in ASP.NET Core
Related
It's my first project to ASP.NET Core Authentication and Authorization and I get this error when I'm trying to pass Enum to [Authorize] attribute :
Error CS1503 Argument 1: cannot convert from
'BasicAuthAPI.Entities.Role' to
'string'
Here is my controller method which gives this error:
[Authorize(Role.Admin)]
[HttpGet]
public IActionResult GetAll()
{
var users = _userService.GetAll();
return Ok(users);
}
Role enum:
public enum Role
{
Admin,
User
}
User Entity:
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Username { get; set; }
public Role Role { get; set; }
[JsonIgnore]
public string PasswordHash { get; set; }
}
And the _userService which I have mentioned in controller:
public class UserService : IUserService
{
private DataContext _context;
private IJwtUtils _jwtUtils;
private readonly AppSettings _appSettings;
public UserService(
DataContext context,
IJwtUtils jwtUtils,
IOptions<AppSettings> appSettings)
{
_context = context;
_jwtUtils = jwtUtils;
_appSettings = appSettings.Value;
}
public AuthenticateResponse Authenticate(AuthenticateRequest model)
{
var user = _context.Users.SingleOrDefault(x => x.Username == model.Username);
// validate
if (user == null || !BCryptNet.Verify(model.Password, user.PasswordHash))
throw new AppException("Username or password is incorrect");
// authentication successful so generate jwt token
var jwtToken = _jwtUtils.GenerateJwtToken(user);
return new AuthenticateResponse(user, jwtToken);
}
public IEnumerable<User> GetAll()
{
return _context.Users;
}
public User GetById(int id)
{
var user = _context.Users.Find(id);
if (user == null) throw new KeyNotFoundException("User not found");
return user;
}
}
How can I pass the Admin Role to [Authorize] attribute?
Either use string constants
public static class Role
{
public static string Admin = "Admin";
public static string User = "User";
}
or you can use nameof
[Authorize(nameof(Role.Admin))]
You can just call .ToString()
[Authorize(Role.Admin.ToString())]
[HttpGet]
public IActionResult GetAll()
{
var users = _userService.GetAll();
return Ok(users);
}
Looking at the answer from Alexander I have found the following SO post which highlights the difference between nameof and ToString: What is the difference between MyEnum.Item.ToString() and nameof(MyEnum.Item)?
PROBLEM:
System.InvalidCastException: 'Unable to cast object of type 'Microsoft.EntityFrameworkCore.Internal.InternalDbSet1[Microsoft.AspNetCore.Identity.IdentityUser1[System.Int32]]' to type 'System.Linq.IQueryable`1[DAL.User]'.'
RELEVANT CODE:
...
public class SocialNetworkDbContext : IdentityDbContext<IdentityUser<int>, IdentityRole<int>, int>
...
public IQueryable<User> FindAll()
{
var allUsers = (IQueryable<User>)_socialNetworkDbContext.Users;
if (allUsers == null)
{
throw new NoRecordFoundException();
}
return allUsers;
TRIED:
public class SocialNetworkDbContext : IdentityDbContext<User>, IdentityRole<int>, int>
//no exception but this code breaks
var result = await _userManager.CreateAsync(user, model.Password);
await _userManager.AddToRoleAsync(user, model.Role);
public IQueryable FindAll()
{
var allUsers = (IQueryable)_socialNetworkDbContext.Users.AsQueryable();
if (allUsers == null)
{
throw new NoRecordFoundException();
}
return allUsers;
//the same exception
3)
public IQueryable<User> FindAll()
{
var allUsers = (IQueryable<User>)(IEnumerable<User>)_socialNetworkDbContext.Users;
if (allUsers == null)
{
throw new NoRecordFoundException();
}
return allUsers;
// the same exception (unable to cast to IEnumerable). Cast to ICollection (unable to cast to ICollection)
Would be very thankful for any advice!!!
You should change your DbContext to use the actual user type:
public class SocialNetworkDbContext : IdentityDbContext<User, IdentityRole<int>, int>
{
}
If you have a class for the roles, you should use that as the generic type argument as well.
This way you won't need any type casts.
From your code, it seems that the _socialNetworkDbContext.Users was stored the IdentityUser, instead of User model, right? So, after query data from the Users table, you could use the following code to convert the query result:
public IQueryable<User> FindAll()
{
var allUsers = _socialNetworkDbContext.Users.Select(c => new User()
{
UserName = c.UserName,
Email = c.Email,
//... other properties
}).AsQueryable();
if (allUsers == null)
{
throw new NoRecordFoundException();
}
return allUsers;
}
Update
You can refer the following sample code:
Add an ApplicationUser class to customize the Identity User model:
public class ApplicationUser : IdentityUser<int>
{
public string CustomTag { get; set; }
}
Use the ApplicationUser type as a generic argument for the context:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, IdentityRole<int>, int>
{
public DbSet<ApplicationUser> ApplicationUsers { get; set; }
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
}
Update Pages/Shared/_LoginPartial.cshtml and replace IdentityUser with ApplicationUser:
#using Microsoft.AspNetCore.Identity
#using WebApp1.Areas.Identity.Data
#inject SignInManager<ApplicationUser> SignInManager
#inject UserManager<ApplicationUser> UserManager
Update the Startup.ConfigureServices and replace IdentityUser with ApplicationUser:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDatabaseDeveloperPageExceptionFilter();
services.AddIdentity<ApplicationUser, IdentityRole<int>>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultUI()
.AddDefaultTokenProviders();
services.AddControllersWithViews();
}
Then, enable migration and generate the database.
After creating new user, the AspNetUser table data as below:
Create a UserViewModel and add the required properties:
public class UserViewModel
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Tag { get; set; }
}
Then, in the Controller, use the following code to query the user table:
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly ApplicationDbContext _context;
public HomeController(ILogger<HomeController> logger, ApplicationDbContext context)
{
_logger = logger;
_context = context;
}
public IActionResult Index()
{
var result = FindAll();
return View();
}
public IQueryable<UserViewModel> FindAll()
{
var allUsers = _context.Users.Select(c => new UserViewModel()
{
UserId = c.Id,
UserName = c.UserName,
Tag = c.CustomTag
});
//if (allUsers == null)
//{
// throw new NoRecordFoundException();
//}
return allUsers;
}
The result as below:
try First(); or FirstOrDefault();
change your code :
public async Task<List<User>> GetAllUsers()
{
var allUsers = await _socialNetworkDbContext.Users.ToListAsync();
if (allUsers == null)
{
throw new NoRecordFoundException();
}
return allUsers;
}
My Employee request:
namespace API.Requests {
public class EmployeeRequest {
public string Name { get; set; }
...
}
public static class Extensions {
public static Employee ToEntity(this EmployeeRequest request) => new Employee {
Name = request.Name,
//UserId = ...
...
};
}
So in my controller I have:
[HttpPost]
public async Task<ActionResult> Poststring( [FromForm] EmployeeRequest request )
{
var employee = request.ToEntity();
return Ok(employee.UserId);
}
So, what I need is that inside the ToEntity function modify the UserId field through the UserManager so that the entity that I get after executing the ToEntity function includes the UserId.
Thank you! :D
So, what I need is that inside the ToEntity function modify the UserId
field through the UserManager so that the entity that I get after
executing the ToEntity function includes the UserId.
Just try this code:
public class HomeController : Controller
{
private readonly UserManager<IdentityUser> _userManager;
public HomeController(UserManager<IdentityUser> userManager)
{
_userManager = userManager;
}
[HttpPost]
public async Task<ActionResult> Poststring([FromForm] EmployeeRequest request)
{
var employee = await request.ToEntity(_userManager, User);
return Ok(employee.UserId);
}
}
public static class Extensions
{
public async static Task<Employee> ToEntity(this EmployeeRequest request,
UserManager<IdentityUser> _userManager, ClaimsPrincipal user) => new Employee
{
UserId = (await _userManager.GetUserAsync(user)).Id.ToString(),
Name = request.Name,
};
}
I designed an ASP.NET Core Razor Pages application implementing dropdown list class and using the class as a base for Create, Read and Update classes.
Now I want to implement anonymous authentication and I have created another class for this which should ideally be the base class for the Create, Read and Update classes. When I tried to add it, the system says I cannot use 2 base classes.
How can I use multiple base classes in ASP.NET Core Razor (MVVM)
I tried using both classes but that triggered an error stating I cannot use more than one base class
My dropdown list base class
public class GLRefPageModel: PageModel
{
public SelectList GLRefNameSL { get; set; }
public void PopulateGLRefDropDownList(strMaterialsTransactContext _context, object selectedGLRef = null)
{
var GLRefsQuery = from d in _context.GLRef
select d;
GLRefNameSL = new SelectList(GLRefsQuery.AsNoTracking(), "ID", "Description", selectedGLRef);
}
}
My Authentication base class
public class DI_BasePageModel : PageModel
{
protected ApplicationDbContext Context { get; }
protected IAuthorizationService AuthorizationService { get; }
protected UserManager<IdentityUser> UserManager { get; }
public DI_BasePageModel(
ApplicationDbContext context,
IAuthorizationService authorizationService,
UserManager<IdentityUser> userManager) : base()
{
Context = context;
UserManager = userManager;
AuthorizationService = authorizationService;
}
}
My Edit Class
public class EditModel : GLRefPageModel
{
private readonly strMaterialsTransact.Models.strMaterialsTransactContext _context;
public EditModel(strMaterialsTransact.Models.strMaterialsTransactContext context)
{
_context = context;
}
[BindProperty]
public strMovement strMovement { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
if (strMovement == null)
{
return NotFound();
}
//select the current GLRef
PopulateGLRefDropDownList(_context, strMovement.GLRefID);
return Page();
}
public async Task<IActionResult> OnPostAsync(int? id)
{
if (!ModelState.IsValid)
{
return Page();
}
var strMovementToUpdate = await _context.strMovement.FindAsync(id);
if (await TryUpdateModelAsync<strMovement>(
strMovementToUpdate,
"strmovement", //prefix for form value
s => s.ID, s => s.TransactionDate, s => s.QtyFromStore, s => s.IDPartNbr,
s => s.QtyToStore, s => s.GLRefID, s => s.ShopOrder, s => s.TransactionReason, s => s.TransactionReason,
s => s.OwnerID, s => s.TimeLastAccessed, s => s.Initials, s => s.LastUser))
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
//**Select GLRef if TryUpdateModelAsync fails
PopulateGLRefDropDownList(_context, strMovementToUpdate.GLRefID);
return Page();
}
}
I expect to me able to call the base class for my dropdown list operation in my Create, Update and Read operations and also be able to call (and use) the class for the anonymous authentication exercise
I have been able to solve the problem by using composition design pattern all the classes into the DI_BasePageModel class as follows:
public class DI_BasePageModel : PageModel
{
protected ApplicationDbContext Context { get; }
protected IAuthorizationService AuthorizationService { get; }
protected UserManager<IdentityUser> UserManager { get; }
public DI_BasePageModel(
ApplicationDbContext context,
IAuthorizationService authorizationService,
UserManager<IdentityUser> userManager) : base()
{
Context = context;
UserManager = userManager;
AuthorizationService = authorizationService;
}
public SelectList GLRefNameSL { get; set; }
public void PopulateGLRefDropDownList(ApplicationDbContext _context, object selectedGLRef = null)
{
var GLRefsQuery = from d in _context.GLRef
select d;
GLRefNameSL = new SelectList(GLRefsQuery.AsNoTracking(), "GLRefID", "Description", selectedGLRef);
}
Thanks for pointing it out Chris Pratt
In the controller code below, only users who are in the "Administrator" role can access the GetData() action method, because of the controller-level AuthorizeAttribute. But I also want users who only are in "Manager" role to have access to the GetData() action method.
[Authorize(Roles = "Administrator")]
Public class AdminController : Controller
{
[Authorize(Roles = "Administrator, Manager")]
public IActionResult GetData()
{
}
}
Is there an option like OverrideAuthorization attribute available in .NET Core framework to achieve this requirement?
Was able to find a solution after long time of analysis on the Authorization assemblies.
In the startup.cs file, add the Authorization as follows:
services.AddAuthorization(options =>
{
var roles = new List<string>{ Role.Administrator, Role.Manager};
var requirement =
new List<IAuthorizationRequirement> {new AdminManagerAuthorizationOverrideOthers(roles) };
var sharedAuthentication =
new AuthorizationPolicy(requirement,
new List<string>());
options.AddPolicy(name: "AdminManager", policy: sharedAuthentication);
options.AddPolicy(name: "Administrator", configurePolicy: policy => policy.RequireAssertion(e =>
{
if (e.Resource is AuthorizationFilterContext afc)
{
var noPolicy = afc.Filters.OfType<AuthorizeFilter>().Any(p =>
p.Policy.Requirements.Count == 1 &&
p.Policy.Requirements.Single() is AdminManagerAuthorizationOverrideOthers);
if (noPolicy)
return true;
}
return e.User.IsInRole(Role.Administrator);
}));
});
Create a class in any namespace that Inherits "RolesAuthorizationRequirement" from "Microsoft.AspNetCore.Authorization.Infrastructure" namespace as follows:
public class AdminManagerAuthorizationOverrideOthers : RolesAuthorizationRequirement
{
public AdminManagerAuthorizationOverrideOthers(IEnumerable<string> allowedRoles) : base(allowedRoles)
{
}
}
Then, decorate the controller and action method as follows:
[Authorize(Policy = "Administrator")]
Public class AdminController : Controller
{
public IActionResult GetData()
{
}
[Authorize(Policy = "AdminManager")]
public IActionResult AdministratorOnly()
{
}
}
Ideally, you want to narrow down the restriction to Action Method, because in Controller Initialization step, it checks Controller's Authorize filter first before Action filters.
[Authorize(Roles = "Administrator, Manager")]
Public class AdminController : Controller
{
public IActionResult GetData()
{
}
[Authorize(Roles = "Administrator")]
public IActionResult AdministratorOnly()
{
}
}
In ASP.NET Core 2.1 you can do it. Check this: https://learn.microsoft.com/en-us/aspnet/core/security/authorization/roles?view=aspnetcore-2.1
You can also lock down a controller but allow anonymous,
unauthenticated access to individual actions.
[Authorize(Roles = "Admin,Employee")] // admin or employee
public class XController : Controller
{
[Authorize(Roles = "Admin")] // only admin
public ActionResult ActionX() { ... }
[AllowAnonymous] // anyone
public ActionResult ActionX() { ... }
}
All above is right, i just want to give a full example easy for all
My case is Asp.Net Core 3.1
Startup.js (ConfigureServices):
services.AddIdentity<ApplicationUser, IdentityRole>(config =>
{
config.User.RequireUniqueEmail = false; // óíèêàëüíûé email
config.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 -._#+";
config.SignIn.RequireConfirmedEmail = false;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddUserManager<UserManager<ApplicationUser>>()
.AddRoleManager<RoleManager<IdentityRole>>()
.AddDefaultTokenProviders();
services.AddAuthorization(options =>
{
options.AddPolicy("User", policy => {
policy.RequireClaim("User");
});
options.AddPolicy("Admin", policy => {
policy.RequireRole("Admin");
});
});
services.AddScoped<IAuthorizationHandler, RolesAuthorizationHandler>();
Startup.js (Configure):
app.UseAuthentication();
app.UseAuthorization();
Controller:
[Authorize(Policy = "Admin")]
public class RoleController : Controller
Handler-Example:
public class RolesAuthorizationHandler : AuthorizationHandler<RolesAuthorizationRequirement>, IAuthorizationHandler
{
private readonly RoleManager<IdentityRole> _roleManager;
private readonly UserManager<ApplicationUser> _userManager;
public RolesAuthorizationHandler(RoleManager<IdentityRole> roleManager, UserManager<ApplicationUser> userManager)
{
_roleManager = roleManager;
_userManager = userManager;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
RolesAuthorizationRequirement requirement)
{
if (context.User == null || !context.User.Identity.IsAuthenticated)
{
context.Fail();
return Task.CompletedTask;
}
var validRole = false;
if (requirement.AllowedRoles == null ||
requirement.AllowedRoles.Any() == false)
{
validRole = true;
}
else
{
var claims = context.User.Claims;
//var userName = claims.FirstOrDefault(c => c.Type == "UserName").Value;
var allowedRoles = requirement.AllowedRoles;
var loggedInUserTask = _userManager.GetUserAsync(context.User);
loggedInUserTask.Wait();
var user = loggedInUserTask.Result;
var roles = _userManager.GetRolesAsync(user);
roles.Wait();
var roleList = roles.Result;
validRole = roleList.Where(p => allowedRoles.Contains(p.ToString())).Any();
}
if (validRole)
{
context.Succeed(requirement);
}
else
{
context.Fail();
}
return Task.CompletedTask;
}
}
I While updating a project that used to exist, I moved the old user table to the user table in the new identity database. Later, I defined roles at the table level for them, and with the RoleManager I wrote in this way, I left his next administration to the step. Quite successful. In my case, many people probably updated their old projects. However, I did not have such a post and wanted to share it.
The following section is for them:
public class RoleAssignViewModel
{
public string RoleId { get; set; }
public string RoleName { get; set; }
public bool HasAssign { get; set; }
}
public class RoleViewModel
{
[Required(ErrorMessage = "Fill the role.")]
[Display(Name = "Role Name")]
public string Name { get; set; }
}
[Authorize(Policy = "Admin")]
public class RoleController : Controller
{
private readonly RoleManager<IdentityRole> _roleManager;
private readonly UserManager<ApplicationUser> _userManager;
public RoleController(RoleManager<IdentityRole> roleManager, UserManager<ApplicationUser> userManager)
{
_roleManager = roleManager;
_userManager = userManager;
}
public async Task<IActionResult> RoleAssign(string id)
{
ApplicationUser user = await _userManager.FindByIdAsync(id);
List<IdentityRole> allRoles = _roleManager.Roles.ToList();
List<string> userRoles = await _userManager.GetRolesAsync(user) as List<string>;
List<RoleAssignViewModel> assignRoles = new List<RoleAssignViewModel>();
allRoles.ForEach(role => assignRoles.Add(new RoleAssignViewModel
{
HasAssign = userRoles.Contains(role.Name),
RoleId = role.Id,
RoleName = role.Name
}));
return View(assignRoles);
}
[HttpPost]
public async Task<ActionResult> RoleAssign(List<RoleAssignViewModel> modelList, string id)
{
ApplicationUser user = await _userManager.FindByIdAsync(id);
foreach (RoleAssignViewModel role in modelList)
{
if (role.HasAssign)
await _userManager.AddToRoleAsync(user, role.RoleName);
else
await _userManager.RemoveFromRoleAsync(user, role.RoleName);
}
return RedirectToAction("Index", "User");
}
public IActionResult RoleList()
{
return View(_roleManager.Roles.ToList());
}
public async Task<IActionResult> DeleteRole(string id)
{
IdentityRole role = await _roleManager.FindByIdAsync(id);
IdentityResult result = await _roleManager.DeleteAsync(role);
if (result.Succeeded)
{
//Başarılı...
}
return RedirectToAction("Index");
}
public async Task<IActionResult> CreateRole(string id)
{
if (id != null)
{
IdentityRole role = await _roleManager.FindByIdAsync(id);
return View(new RoleViewModel
{
Name = role.Name
});
}
return View();
}
[HttpPost]
public async Task<IActionResult> CreateRole(RoleViewModel model, string id)
{
IdentityResult result = null;
if (id != null)
{
IdentityRole role = await _roleManager.FindByIdAsync(id);
role.Name = model.Name;
result = await _roleManager.UpdateAsync(role);
}
else
result = await _roleManager.CreateAsync(new IdentityRole { Name = model.Name });
if (result.Succeeded)
{
//Başarılı...
}
return View();
}
//[Authorize]
public IActionResult UserRoleList()
{
return View(_userManager.Users);
}
}
Found something here I am using: https://github.com/dotnet/aspnetcore/issues/8149#issuecomment-471927034
/// <summary>
/// https://github.com/dotnet/aspnetcore/issues/8149#issuecomment-471927034
/// </summary>
public class OverrideFilter : ActionFilterAttribute
{
public Type Type { get; set; }
}
public class OverrideFilterProvider : IFilterProvider
{
public int Order => 1;
public void OnProvidersExecuted(FilterProviderContext context) { }
public void OnProvidersExecuting(FilterProviderContext context)
{
if (context.ActionContext.ActionDescriptor.FilterDescriptors != null)
{
//Check whether the method has any OverrideFilter
var overrideFilters = context.Results.Where(filterItem => filterItem.Filter is OverrideFilter).ToList();
foreach (var overrideFilter in overrideFilters)
{
//Remove the filters of the corresponding type, but with smaller scope
context.Results.RemoveAll(filterItem =>
filterItem.Descriptor.Filter.GetType() == ((OverrideFilter)overrideFilter.Filter).Type &&
filterItem.Descriptor.Scope < overrideFilter.Descriptor.Scope);
}
}
}
}
public class OverrideAuthorization : OverrideFilter
{
public OverrideAuthorization()
{
Type = typeof(AuthorizeFilter);
}
}
/// <summary>
/// https://stackoverflow.com/questions/16606281/linq-to-remove-certain-elements-from-a-ilistt-based-on-a-ilistint
/// </summary>
public static class IListExt
{
public static int RemoveAll<T>(this IList<T> list, Predicate<T> match)
{
int count = 0;
for (int i = list.Count - 1; i >= 0; i--)
{
if (match(list[i]))
{
++count;
list.RemoveAt(i);
}
}
return count;
}
}
Finally we inject it as follows (I am not sure this is the right wat to inject it, but it works);
services.TryAddEnumerable(ServiceDescriptor.Singleton<IFilterProvider, OverrideFilterProvider>());
Use like
[Authorize(Policy = "ControllerPolicy")
public class MyController : Controller
{
[OverrideAuthorization]
[Authorize(Policy = "ActionPolicy")]
public IActionResult MyAction()
{
//Only ActionPolicy will be applied, while ControllerPolicy will be ignored
}
}