views:

39

answers:

2

I have a ASP.NET MVC website hosted in IIS. Sometimes I push changes and user's browser may still using the previous files, causing functionality problems. It is because the browser is caching those files right? What can I do to ensure the user browser loading the updated files??

Thanks!

+1  A: 

This is what ETag, If-None-Match (or If-Not-Modified), and HTTP 304 resopnses are for.

If a file is sent with an ETag header and an acceptable caching policy, the browser will cache the file, and for each subsequent request will send the If-None-Match header.

The web server should check that the generated ETag of the file matches the If-None-Match request, and return either an HTTP 200 with the new content, or an HTTP 304 indicating that the cached version is still current.

Here is how I'm, using it in ASP.NET MVC 1.0:

public ActionResult ViewAvatar(long id)
{
    UserAvatar avatar = this.AppManager.GetUserAvatar(id);

    if (avatar != null && true)
    {
        byte[] imageData = avatar.Avatar.ToArray();

        string eTag = LanLordzApplicationManager.CalculateMd5(imageData);

        if (this.Request.Headers["If-None-Match"] == eTag)
        {
            return this.NotModified(
                HttpCacheability.Public,
                DateTime.Now.AddMinutes(2)
            );
        }

        string mimeType = this.AppManager.GetImageMimeType(imageData);

        return this.Image(
            imageData,
            mimeType,
            HttpCacheability.Public,
            DateTime.Now.AddMinutes(2),
            eTag
        );
    }
    else
    {
        return this.HttpError(404, this.View("NotFound"));
    }
}
John Gietzen
Thanks for your reply. So do I set the Response's status code in my updated controllers?(Sorry, not understanding this ETag thing)What if the updated file is a js or a css though?
fishiefishie
Well, .JS and .CSS files are generally sent by the web server directly, not through ASP. You will have to configure the cacheability under the IIS settings. That is, you may need to lower the cache time, and use ETags.
John Gietzen
+1  A: 

The easiest thing to do is append a date or version number on the URL as a querystring. Something like:

<link rel="stylesheet" href="http://mysite.com/styles.css?2010-06-10-0700"&gt;

or

<script type="text/javascript" src="http://mysite.com/js/main.js?v1234"&gt;&lt;/script&gt; 

The browser will request a new file because the URL is different. The server will ignore the querystring (unless you are doing something clever).

The etag/last-modified suggestions are good, but do not address the problem of "telling" the browser that there is a new version of the file.

Matt Sherman
+1: Yeah, I had kinda skipped the cache-invalidation side of this.
John Gietzen