1

My team is building a simple MVC site for very low end "feature" phones. One problem we have is that certain phone aggressively cache HTML, so what the user actually gets to see is not what we intend. An extreme example is, a user registers and gets a "thank you page". Another user on the same device then tries to register. The phone simply serves the cached page without creating a new account.

In the past I've dealt with this by adding a "cache buster" querystring to things I don't want cached, eg all pages will be served in the format

http://domain.com/controller/route?cb=somerandomstringofnumbers

In this case we'd need to do this for all URLs in the site - this includes the URLs auto-generated by Controller actions such as RedirectToAction or Redirect and also the Razor Url.Action, Html.BeginForm, Html.ActionLink etc.

Now obviously I could decorate the Razor HTML helpers (or extend them) and add the argument to an controller action, but it seems to me that because the actual URLs generated by these built in methods are auto-generated from the Controller/Action params passed in, there should be a way to hijack that process.

Unfortunately the MS classes are protected - I'm mostly looking in System.Web.Routing.Routes.

I've tried a few things I've found online but they are not MVC5 (dating back to 2008) and it seems the framework has changed significantly.

eg, from http://forums.asp.net/t/1216840.aspx?Append+value+to+all+urls+built+by+RouteCollection+GetUrl

public class SessionAppendingRouteHandler : IRouteHandler
{
   public IHttpHandler GetHandler(RequestContext context)
   {
       SessionAppendingHttpHandler handler = new SessionAppendingHttpHandler();
       handler.RequestContext = context;
       return handler;
   }
}




public class SessionAppendingHttpHandler : MvcHandler
{
    public override ProcessRequest(RequestContext context)
    {
          //append your sid here
    }
}


// and in the route setup

RouteTable.Routes.Add( new Route
{
   Url = "/[controller].mvc/[action]/",
   Defaults = new { action = "index" },
   RouteHandler = typeof(SessionAppendingRouteHandler)
});

This I cant get to work as the framework has changed too much, but it looks very close to what I would like to achieve.

I feel like I'm in the right area, but I've hit a brick wall.

Any suggestions?

scudsucker
  • 934
  • 1
  • 10
  • 16
  • Are you sure you need such a roundabout solution? Which specific devices/browsers are you having trouble with? Have you tried making sure all your non-idempotent operations are done with POSTs and setting Cache-Control: no-cache? – Iain Galloway Jun 18 '15 at 14:00
  • no one here has time to go through all that, please try coming straight to the point – manish Jun 18 '15 at 14:00
  • @Iain Galloway - Nokia 5330, with its native browser. Cache-Control is set. We are using POST where ever we should. It is bizarre.. hence I'm looking at desperate measures. It is so far only reported on that device but we are targeting lots of low end devices, so reports will keep coming in. – scudsucker Jun 18 '15 at 14:14
  • 1
    @Manish - you really don't have to help out if you don't want to read the detail. No one here is forcing you to read it all. – scudsucker Jun 18 '15 at 14:15
  • FYI, If you read the entirety of the page you posted a link to you'll find that the initially proposed solution did not do what he or you desire. The solution he ended up with was adding lots of overrides which you state you want to avoid. – Sacrilege Jun 18 '15 at 15:10
  • Will these old phones obey cache expiration instructions? If they do you could set the maximum age to something very short. See the `cacheControl` web.config element, or use `Response.Expires = -1`. You could write an action filter to do this and set it on every page by adding it to `GlobalFilters`. See http://stackoverflow.com/questions/5352883/mvc3-razor-expiring-pages – Andy Nichols Jun 18 '15 at 16:04
  • @Andy Nichols - That's the route I'm going now. In in the throes of testing it - just got into work, and testing on the ancient phone is very slow. However, I have my doubts that it will work. – scudsucker Jun 19 '15 at 07:17

1 Answers1

0

This is quite old, but let me answer based on how I solved a similar problem:

Instead of having it as query string, have the cb as a route value just as action and controller are route values. You can do this by registering a route; for instance:

 routes.MapRoute(
     name: "CB",
     url: "{cb}/{controller}/{action}/{id}",
     defaults: new { cb = "3600", area = "", id = UrlParameter.Optional }
 );

If the value for cb is not a constant, then you can find a convenient point to set the cb for each user session. A good place will be after a successful login. With this, you'll now need to provide just two custom methods for RedirectToAction and ActionLink. Your implementation will simply package a RouteValueDictionary and then pass it in to MVC's own implementation using the appropriate overloads.

Soma Mbadiwe
  • 1,594
  • 16
  • 15