In my MVC 4 web app, I have a requirement to ask users to choose a payment method after they have been using the app for a certain number of days.
I've implemented this by making a controller base class, and making all my controllers inherit from this. The base class has the following code:
public class MyBaseController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (WebSecurity.IsAuthenticated)
{
var pay = PaymentDetails.LoadByMember(WebSecurity.CurrentUserId);
if (pay.ForceToChooseMandate)
{
filterContext.Result = RedirectToAction("Choose", "Payment");
}
}
base.OnActionExecuting(filterContext);
}
}
The Choose action has links allowing you to set up payment details or to defer choosing for a while. If either of these links are visited then pay.ForceToChooseMandate returns false on subsequent calls, allowing normal operation of the app to be resumed for the user.
That first time an action gets visited, OnActionExecuting fires and the redirect works as fine. But if the user visits the action a second time, OnActionExecuting never fires, and they are redirected to the Choose action again, even though pay.ForceToChooseMandate would have evaluated to false for them this time.
However if they visit a previously unvisited action, OnActionExecuting fires as expected.
How can I stop this happening, and have OnActionExecuting always fire so it can always reflect the users' current state?
The problem is that the result of your first execution is cached.
In order to achieve what you want, you need to disable caching for the Actions in questions. You can do this by decorating those Actions with
OutputCacheAttributeYou can also keep cache enabled but specify
VaryByParamto refresh it when needed.Alternatively you can remove the cache of an action from another action by using