Search code examples
c#asp.net-coredependency-injectioncustom-action-filter

Register generic Action Filter with multiple types from DI container


I'm working on an Asp.net core 5 targeted .net 5. I used an Action filter as generic. This action filter will check the model's Id if any another object has the same Id in the TEntity. TEntity is the generic type will be replaced by the name of entity to be check-in if an object exist or not.

What I tried:

public class ShouldExistFilter<TEntity>:IActionFilter where  TEntity : class
{

    private readonly AppDbContext _dbContext;

    public ShouldExistFilter(AppDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public void OnActionExecuting( ActionExecutingContext context )
    {
        context.ActionArguments.TryGetValue( "model" , out object model );

        var result= _dbContext.Set<TEntity>().Find( model.GetType().GetProperty( "Id" ).GetValue( model ) );

        if ( result!=null )
        {
          // Some logic here
        }

       
    }

    public void OnActionExecuted( ActionExecutedContext context )
    {
        
    }

}

How I used it with actions:

1st example:

[ServiceFilter(typeof(ShouldExistFilter<SchoolSubject>))]
public async Task<IActionResult> Edit(SchoolSubjectModel model)
{
// Some logic here
}

2nd example:

[ServiceFilter(typeof(ShouldExistFilter<Student>))]
public async Task<IActionResult> Edit(StudentModel model)
{
// Some logic here
}

The problem: When I try to register the ShouldExistFilter in ConfigureServices method I have to register it with all entities that may I used with the filter and this is not practical for me because I have a lot of entities.

At now I should do :

services.AddScoped<ShouldExistFilter<SchoolSubject>>(); 

services.AddScoped<ShouldExistFilter<Student>>();  
      
services.AddScoped<ShouldExistFilter<Absence>>();

...

The question:

How can I register the ShouldExistFilter one time in DI Container and use it with any Type ? or is there any way to reach my object ?


Solution

  • Instead of a service filter attribute, you can also use the [TypeFilter] attribute which will allow you to create a filter with dependencies without that filter having to be registered with the DI container itself:

    [TypeFilter(typeof(ShouldExistFilter<SchoolSubject>))]
    public async Task<IActionResult> Edit(SchoolSubjectModel model)
    {
        // Some logic here
    }