1

I'm working on an Asp.net core 5 project targeted .Net 5, I try to create an Action filter that will receive a property name, and he will recieve a TEntity generic type (represent the table to select from) and catch the submitted model and get the property value from it (model), this Action Filter will look in database if a record already has the same value in the past property inside the table passed in TEntity.

My Action filter:

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

    private readonly AppDbContext _dbContext;
    public           string     PropertyToBeChecked { get; set; }

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

    public void OnActionExecuting( ActionExecutingContext context )
    {
      // Some logic here that uses the PropertyToBeChecked's value
    }


    }

    public void OnActionExecuted( ActionExecutedContext   context )
    {
        
    }

}

The problem: When I try to apply the filter on my action I don't know how to pass the PropertyToBeChecked value.

I paused here :

[TypeFilter(typeof(RecordShouldNotExistFilter<PedagogicalSequence>))]
public async Task<IActionResult> Create( PedagogicalSequenceModel model )
{
}

The question : How can I pass the PropertyToBeChecked value ? or how to achieve my object with another way ? except using Action parameters

JOCKH
  • 339
  • 4
  • 15
  • would this [SO thread](https://stackoverflow.com/questions/39181390/how-do-i-add-a-parameter-to-an-action-filter-in-asp-net) help? – timur Apr 21 '21 at 04:16

1 Answers1

2

You can get the property to be checked in the constructor of your filter, like so:

public RecordShouldNotExistFilter(AppDbContext dbContext, string propertyToBeChecked)
{
    _dbContext = dbContext;
    PropertyToBeChecked = propertyToBeChecked;
}

And then pass that value into the filter attribute:

[TypeFilter(typeof(RecordShouldNotExistFilter<PedagogicalSequence>), Arguments = new object[] { "PropertyName" })]
public async Task<IActionResult> Create(PedagogicalSequenceModel model)
{
}

Generic attributes aren't supported so your other option is to make a non-generic attribute following this answer and get the entity type through a Type parameter. You would then use reflection to get the generic implementation:

public class RecordShouldNotExistFilterAttribute : TypeFilterAttribute
{
    public RecordShouldNotExistFilterAttribute(Type entityType, string propertyToBeChecked) 
        : base(typeof(RecordShouldNotExistFilter<>).MakeGenericType(entityType))
    {
        Arguments = new object[] { propertyToBeChecked };
    }
}

public class RecordShouldNotExistFilter<TEntity> : IActionFilter where TEntity : class
{
    readonly AppDbContext _dbContext;
    public string PropertyToBeChecked { get; set; }

    public RecordShouldNotExistFilter(AppDbContext dbContext, string propertyToBeChecked)
    {
        _dbContext = dbContext;
        PropertyToBeChecked = propertyToBeChecked;
    }
}

This would allow you to do this instead:

[RecordShouldNotExistFilter(typeof(PedagogicalSequenceModel), "PropertyName")]
public async Task<IActionResult> Create(PedagogicalSequenceModel model)
Mike Marynowski
  • 3,156
  • 22
  • 32