在 ASP.NET MVC 中执行控制器后如何将数据发送到 Action Filter?

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

以下是我在控制器中的动作。我需要将 ProductIdQuantity 传递给过滤器 SessionCheck。除了TempData还有别的方法吗?

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

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

以下是我的操作过滤器:

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

好问题。据我所知,无法从您的过滤器中直接 调用参数——即使您可以通过ActionDescriptor.GetParameters() 方法。

源值

但是,您可以使用 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 从它们的 source 集合中直接访问这些值。

例子

因此,例如,如果您的值是从表单集合中检索的——我认为可能是这种情况,因为这是一个 [HttpPost] 操作——您的代码可能类似于:

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);
}

验证

请记住,从技术上讲,您的 ActionFilterAttribute 可以应用于任意数量的操作,因此您应该意识到这一点,而不是 假设 这些参数将可用。如果需要,您可以使用 ActionDescriptor.ActionName 属性 来验证上下文:

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

或者,您也可以使用上面提到的 ActionDescriptor.GetParameters() 方法来简单地评估参数是否存在,而不管动作的名称是什么。

注意事项

这种方法有一些局限性。最值得注意的是:

  1. 它将无法检索对操作的内部调用的值,并且
  2. 它不会执行任何模型绑定,这对于更复杂的对象来说可能是个问题。

其他框架

您指定 ASP.NET MVC。对于使用 ASP.NET Core 阅读本文的任何人来说,class 库有点不同,并提供一些额外的功能(例如 TryGetValue() 用于调用 HttpRequest 方法)。此外,它还提供对 BoundProperties 集合的访问, 可能 提供额外的选项——尽管我还没有深入研究这些数据来确认。