Victor Rodrigues
Victor Rodrigues

Reputation: 11711

Can eTag be used for smart client caching in asp.net MVC as in Rails?

I've found in this screencast ¹ that you can do, in Ruby on Rails, a better client caching ² considering REST + model for filling eTag. Way more smart than render all the http body and only after all this, calculate the eTag, as usual.

This property can make the client caching more model-oriented when using GET, so I think this is great for performance.

I didn't see anywhere someone making this with asp.net MVC. Would it be as easy as I saw this guy doing in Rails?

Upvotes: 1

Views: 813

Answers (2)

valerysntx
valerysntx

Reputation: 526

Use ActionFilterAttribute to update response via filter

public class ETagAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.HttpContext.Response.Filter = new ETagFilter(filterContext.HttpContext.Response, filterContext.RequestContext.HttpContext.Request);
    }
}

public class ETagFilter : MemoryStream
{
    private HttpResponseBase _response = null;
    private HttpRequestBase _request;
    private Stream _filter = null;

    public ETagFilter(HttpResponseBase response, HttpRequestBase request)
    {
        _response = response;
        _request = request;
        _filter = response.Filter;
    }

    private string GetToken(Stream stream)
    {
        byte[] checksum = new byte[0];
        checksum = MD5.Create().ComputeHash(stream);
        return Convert.ToBase64String(checksum, 0, checksum.Length);
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        byte[] data = new byte[count];
        Buffer.BlockCopy(buffer, offset, data, 0, count);
        var token = GetToken(new MemoryStream(data));

        string clientToken = _request.Headers["If-None-Match"];

        if (token != clientToken)
        {
            _response.Headers["ETag"] = token;
            _filter.Write(data, 0, count);
        }
        else
        {
            _response.SuppressContent = true;
            _response.StatusCode = 304;
            _response.StatusDescription = "Not Modified";
            _response.Headers["Content-Length"] = "0";
        }
    }
}

iriginal from: Create ETag filter in ASP.NET MVC

Upvotes: 0

David Andres
David Andres

Reputation: 31781

eTags are an HTTP concept more than they are related to any one server-side technology. I believe RoR may make it easier when compared to IIS/MVC to indicate that a particular file is cached using an eTag.

For IIS/MVC, you have two options of setting up response headers (which can include eTag settings):

  1. In the IIS Content Expiration settings dialog.
  2. Setting up HTTP Handlers or a similar technique so that you specify exactly which response headers you want for a particular request. This is a programmatic variation of step #1. It is necessary if you're streaming database content over the wire, in which case there isn't a real file to speak of.

If there are other ways of making this happen that I haven't listed, I would love to know about them.

Upvotes: 1

Related Questions