I have a generic action filter, and i want to get current model in the OnActionExecuting
method. My current implementation is like below:
public class CommandFilter<T> : IActionFilter where T : class, new()
{
public void OnActionExecuting(ActionExecutingContext actionContext)
{
var model= (T)actionContext.ActionArguments["model"];
}
}
It works well if my all model names are same. But i want to use differnet model names.
How to solve this problem?
Edit
public class HomeController : Controller
{
[ServiceFilter(typeof(CommandActionFilter<CreateInput>))]
public IActionResult Create([FromBody]CreateInput model)
{
return new OkResult();
}
}
In case your controller action has multiple arguments and in your filter you want to select the one that is bound via [FromBody] , then you can use reflection to do the following: public void OnActionExecuting(ActionExecutingContext context) { foreach (ControllerParameterDescriptor param in context. ActionDescriptor.
You just need to test the filter itself. Just create an instance and call the OnActionExecuted() method with test data then check the result. It helps to pull the code apart as much as possible. Most of the heavy lifting is done inside the CsvResult class which can be tested individually.
Using an Action Filter An action filter is an attribute. You can apply most action filters to either an individual controller action or an entire controller. For example, the Data controller in Listing 1 exposes an action named Index() that returns the current time.
The ASP.NET MVC Framework supports four different types of filters.
ActionExecutingContext.ActionArguments is just a dictionary,
/// <summary>
/// Gets the arguments to pass when invoking the action. Keys are parameter names.
/// </summary>
public virtual IDictionary<string, object> ActionArguments { get; }
And you need to loop through it if you need to avoid hardcoded parameter name ("model"). From the same SO answer for asp.net:
When we create a generic action filter that needs to work on a class of similar objects for some specific requirements, we could have our models implement an interface => know which argument is the model we need to work on and we can call the methods though the interface.
In your case you may write something like this:
public void OnActionExecuting(ActionExecutingContext actionContext)
{
foreach(var argument in actionContext.ActionArguments.Values.Where(v => v is T))
{
T model = argument as T;
// your logic
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With