3

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?

Mihai Dinculescu
  • 19,743
  • 8
  • 55
  • 70
colonel32
  • 43
  • 6

1 Answers1

2

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

[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]

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

HttpResponse.RemoveOutputCacheItem("/Home/About");
Mihai Dinculescu
  • 19,743
  • 8
  • 55
  • 70
  • Oh, that makes a lot of sense, thanks. Is there a way I can still benefit from the cacheing that has historically been going on by not disabling it, but programmatically clear the cache on the server side to force those actions to be re-executed next time they are called? – colonel32 Jan 05 '15 at 10:05