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
OutputCacheAttribute
You can also keep cache enabled but specify
VaryByParam
to refresh it when needed.Alternatively you can remove the cache of an action from another action by using