Search code examples
c#asp.net-mvcsessiontempdatacustom-action-filter

How Can I Send Data to the Action Filter after Execution of the controller in ASP.NET MVC?


The following is my action in the controller. I need to pass ProductId and Quantity to the filter SessionCheck. Is there any other way besides TempData?

[SessionCheck]
[HttpPost]
public ActionResult AddToCart(int ProductId, int Quantity)
{
    try
    {
        //my code here 

        return RedirectToAction("Cart");
    }
    catch (Exception error)
    {
        throw error;
    }
}

And the following is my action filter:

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
  // my code here
}

Solution

  • Good question. So far as I'm aware, it's not possible to call the parameters directly from your filter—even though you can retrieve metadata about them via the ActionDescriptor.GetParameters() method.

    Source Values

    You can, however, access these values directly from their source collection using either RequestContext.RouteData, or the RequestContext.HttpContext’s Request property, which can retrieve data from the Form, QueryString, or other request collections. All of these are properties off of the ActionExecutedContext.

    Example

    So, for example, if your values are being retrieved from the form collection—which I assume might be the case, since this is an [HttpPost] action—your code might look something like:

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var request = filterContext.RequestContext.HttpContext.Request;
        Int32.TryParse(request.Form.Get("ProductId"), out var productId);
        Int32.TryParse(request.Form.Get("Quantity"), out var quantity);
    }
    

    Validation

    Keep in mind that, technically, your ActionFilterAttribute can be applied to any number of actions, so you should be aware of that and not assume that these parameters will be available. You can use the ActionDescriptor.ActionName property to validate the context, if necessary:

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.ActionDescriptor.ActionName.Equals(nameof(MyController.AddToCart)) 
        {
            //Retrieve values
        }
    }
    

    Or, alternatively, you can use the ActionDescriptor.GetParameters() method mentioned above to simply evaluate if the parameters exist, regardless of what the name of the action is.

    Caveats

    There are some limitations to this approach. Most notably:

    1. It won't be able to retrieve the values of internal calls to the action, and
    2. It won't execute any model binding, which could be an issue for more sophisticated objects.

    Other Frameworks

    You specify ASP.NET MVC. For anyone reading this who's using ASP.NET Core, the class libraries are a bit different, and offer some additional functionality (such as TryGetValue() for calls to the HttpRequest methods). In addition, it also provides access to the BoundProperties collection, which may provide additional options—though I haven't dug into those data yet to confirm.