How to get the current model in the action filter

I have a common action filter, and I want to get the current model in the OnActionExecuting method. My current implementation is as follows:

 public class CommandFilter<T> : IActionFilter where T : class, new() { public void OnActionExecuting(ActionExecutingContext actionContext) { var model= (T)actionContext.ActionArguments["model"]; } } 

This works well if my names of all models are the 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(); } } 
+7
c # asp.net-core asp.net-core-mvc
source share
3 answers

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 go in cycles if you need to avoid the hard-coded parameter name ("model"). From the same SO answer for asp.net:

When we create a common action filter that should work on a class of similar objects for some specific requirements, we could implement our interface models => know which argument is the model we need to work on, and we can call methods, although the interface.

In this case, you can 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 } } 
+4
source share

You can use the ActionExecutingContext.Controller property

  /// <summary> /// Gets the controller instance containing the action. /// </summary> public virtual object Controller { get; } 

and converting the result to a basic MVC controller to access the model:

 ((Controller)actionExecutingContext.Controller).ViewData.Model 
+4
source share

If your controller action has several 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.Parameters) { if (param.ParameterInfo.CustomAttributes.Any( attr => attr.AttributeType == typeof(FromBodyAttribute)) ) { var argument = context.ActionArguments.FirstOrDefault( arg => arg.Value?.GetType() == param.ParameterType ); var entity = argument.Value; // do something with your entity... 
0
source share

All Articles