4

I have an action that generates a password reset link and emails it to the user

public ActionResult SendResetPasswordEmail(string userName)
{
    var webUser = LoadUser(userName);
    if (webUser != null)
    {
        var token = WebSecurity.GeneratePasswordResetToken(webUser.UserName);
        emailSender.SendPasswordResetEmail(webUser, token, resetAction);
        return new HttpStatusCodeResult(HttpStatusCode.OK);
    }
    return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "No user found with username: " + userName);
}

The first time I call the action from the browser, I get an HTTP 200 response (and hit my breakpoint in the action).

The second time I call the action from the browser, I get an HTTP 304 response indicating that the content is unchanged.

There are no [OutputCache] attributes anywhere in the source file (not on the class or the action).

What is causing the web server to decide that the content is unchanged and return the HTTP 304?

I'm aware of a work-around

https://stackoverflow.com/a/18620970/141172

I'm interested in understanding the root cause for the HTTP 304 response.

Update

Headers on first request:

Request Headers

Request GET /Companies/SendResetPasswordEmail/?userName=ej HTTP/1.1
X-Requested-With    XMLHttpRequest
Accept  */*
Referer http://local:6797/Companies
Accept-Language en-US
Accept-Encoding gzip, deflate
User-Agent  Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
Host    localhost:6797
DNT 1
Connection  Keep-Alive
Cookie  __RequestVerificationToken=sNOBS6qz32LtnJpLWgHHELhaE44DfIVE1LSMUgjzHjcwsvxlUFa4lOSyA5QeB8keLXYL08Psjg29CRI7W73uHLJy6A81; .ASPXAUTH=DAF8AF47E955F723EE9438866BE1B4BFBF91BA01912EF087824F03581DBCA05A4AECA01373FAF40DF0C4D5C17F17DEFA2F85C1B702988B7E0F750BFE19566FC711C7D6BD81D8F0B0ABD68AF5B3D9BA032286361F; ASP.NET_SessionId=5e2gcvkc2p3rji25z5emyqzd; HelixPlugins1.0=IEPlugin1.0

Response Headers

Response    HTTP/1.1 200 OK
Server  ASP.NET Development Server/11.0.0.0
Date    Thu, 03 Apr 2014 23:29:02 GMT
Cache-Control   private, s-maxage=0
Content-Length  0
Connection  Close

NOTE: I changed localhost to local in the above because StackOverflow does not allow links containing localhost to be posted :-)

The browser is Internet Explorer 10.

Community
  • 1
  • 1
Eric J.
  • 147,927
  • 63
  • 340
  • 553
  • Can you verify using Fiddler that on the first request the server is setting HTTP headers allowing caching? If you find no such headers you need a different theory. – usr Apr 03 '14 at 22:49
  • @usr: I posted request and response headers. – Eric J. Apr 03 '14 at 23:33
  • @FelipeOriani: Yes, it is an Ajax call. – Eric J. Apr 03 '14 at 23:46
  • 1
    Just as an aside... This call should probably be a POST and not a GET, since you are performing an action and not requesting a resource. Doing so would have the happy side-effect of not caching. – Eric King Apr 03 '14 at 23:47
  • Well, I do not know if it is related with your problem, but, when we work with jQuery, the ajax calls in `IE` are cached and other browsers work fine. What we do, is set the `$.ajaxSetup({ cache: false });` and every ajax call made by jQuery, a `_` parameter with a random number is added in the url. It make all requests different and we got it working on the IE. Maybe add a random parameter could work in IE. – Felipe Oriani Apr 04 '14 at 00:13
  • Nothing should be returning a 304 because your response does not have any validator headers (etag or Last-Modified). I'm very curious to know what is doing this. – Darrel Miller Apr 04 '14 at 01:24

1 Answers1

2

IE caches ajax responses by default, you need to explicitly tell it not to do any ajax caching by setting your ajax object's cache property to false.

Browsers such as Chrome automatically append a random token to your request to make it unique.

Duy
  • 1,332
  • 1
  • 10
  • 19
  • But setting `[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]` also prevents browser caching. I'm trying to understand what MVC is doing by default that is causing the caching to happen, that can also be overridden by using `OutputCacheAttribute`. I don't want to place the onus on the client developer, as many clients may consume the actions over time. – Eric J. Apr 04 '14 at 00:40
  • you could try adding Location=OutputCacheLocation.Server to your OutputCache attribute. – Duy Apr 04 '14 at 00:56
  • The attribute works exactly as I list it. I'm trying to understand exactly what behavior it changes (that is, understand why the *default* behavior is to allow caching, and exactly what part of the HTTP exchange allows for that caching). – Eric J. Apr 04 '14 at 01:01
  • This isn't a caching issue. It is an issue of who is handling the conditional request and returning the 304. And how can it be handling conditional requests when the response does not contain any validator. That's not compliant with the HTTP spec as far as I know. – Darrel Miller Apr 04 '14 at 01:28