How to change the input parameters using action filters

IMPORTANT This article is to demonstrate how we can intercept the values coming through the request and modify them using action filters. But if the problem is how to customize binding the request values to models then the better way is to go for custom model binders.

Action Filters

Filters are behaviors that can be added to different stages in the ASP.NET MVC request processing pipeline. There are four different types of filters: Authorization, Action, Result and Exception. The Action filters are the ones that are called before and after an action is executed.

One of the interesting thing with the action filters is, we can even change the parameters before passed to an action and that's what we are going to see in this article.

IActionFilter

All the action filters should implement the IActionFilter interface.

public interface IActionFilter
{    
   void OnActionExecuting(ActionExecutingContext filterContext);
   void OnActionExecuted(ActionExecutedContext filterContext);    	
}

The IActionFilter contains two methods. The OnActionExecuting method is called before the action is executed and the OnActionExecuted method is called after the action is executed. In our example we are going to change the parameters before the action is called so we have to override the OnActionExecuting method.

Example

Let say we have a controller named OrdersController with a single action Index that returns the list of orders.

public ActionResult Index(int[] ids)
{
	// Returns all the orders if the array is null else 
	// returns only the orders whose ids are in the array.
}

The Index action takes an integer array (ids) as the input parameter. If the user doesn't pass any id then all the orders will be returned from the action else only the orders of the passed ids will be returned. The important thing is multiple order ids are passed as comma separated values to the action for ex. http://localhost:5555/orders/1,2,3.

Without any customization if the user sends the above request then the value of parameter ids will be null because MVC not converts the comma separated values into an integer array and there comes our custom action filter for rescue. In the custom action filter we read the comma separated values, convert into an integer array and set it to the parameter.

Here we go!

public class ParameterConverterAttribute : FilterAttribute, IActionFilter
{
	private readonly string _parameterName;

	public ParameterConverter(string parameterName)
	{
		_parameterName = parameterName;
	}

	public void OnActionExecuting(ActionExecutingContext filterContext)
	{
		var valueProviderResult = filterContext.Controller.ValueProvider.GetValue(_parameterName);

		if (valueProviderResult != null)
		{
			var orders = valueProviderResult.AttemptedValue.ToString().Split(',');
			filterContext.ActionParameters[_parameterName] = Array.ConvertAll(orders, s => int.Parse(s));
		}
	}

	public void OnActionExecuted(ActionExecutedContext filterContext)
	{
	}
}

The implementation is quite simple! We are reading the parameter's actual value(AttemptedValue) from the ValueProvider and converting it into an integer array. The converted array is assigned to the corresponsing key in the ActionParameters collection. Since we are passing the parameter name in the constructor we can reuse our custom filter in other controller actions as well.

We are done with the implementation and the only thing pending is applying it over the action. Let's do it.

[ParameterConverter("ids")]
public ActionResult Index(int[] ids)
{
	// Returns all the orders if the array is null else 
	// returns only the orders whose ids are in the array.
}

Happy Coding!

Download

blog comments powered by Disqus