开发者

Set ETag for FileResult - MVC 3

MVC 3 RTM. I have an action that returns a file (image/jpeg). I am trying to set the ETag for a file with no success (the etag doesn't come through on header). I have tried both Response.Cache.SetETag and Response.AppenderHeader. If I add my own custom header tag, it works as expected, it just seems to be ETag that I can't set.

Here is the source.

        [HttpGet, OutputCache(Location= OutputCacheLocation.Client, VaryByParam="userId", Duration=3600, NoStore=true)]
        public ActionResult GetImage(string userId)
        {
            byte[] result;

            using (var client = new WebClient())
            {
                client.Credentials = CredentialCache.DefaultCredentials; 
                result = client.DownloadData(string.Format(IntranetUrl, userId));
            }

            Response.Cache.SetETag("00amyWGct0y_ze4lIsj2Mw");
            //or Response.AppendHeader("ETag", "00amyWGct0y_ze4lIsj2Mw");
            Response.AppendHeader("MyHeader", "HelloWorld");

            return File(result, "image/jpeg");
        }

And here is the resource request/response:

> Request
> URL:http://localhost/My开发者_如何转开发App/Employee.mvc/GetImage?userId=myUserId
> Request Method:GET Status Code:200 OK
> Request Headers Accept:*/*
> Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
> Accept-Encoding:gzip,deflate,sdch
> Accept-Language:en-US,en;q=0.8
> Cache-Control:max-age=0
> Connection:keep-alive
> Cookie:ASP.NET_SessionId=mySessionId
> Host:localhost
> Referer:http://localhost/MyApp/Employee/Review/24/Index
> User-Agent:Mozilla/5.0 (Windows; U;
> Windows NT 5.1; en-US)
> AppleWebKit/534.13 (KHTML, like Gecko)
> Chrome/9.0.597.98 Safari/534.13 Query
> String Parameters userId:myUserId
> Response Headers
> Cache-Control:private, no-store,
> max-age=3600 Content-Length:1428
> Content-Type:image/jpeg Date:Thu, 17
> Feb 2011 15:45:30 GMT Expires:Thu, 17
> Feb 2011 16:45:29 GMT
> Last-Modified:Thu, 17 Feb 2011
> 15:45:29 GMT MyHeader:HelloWorld
> Server:Microsoft-IIS/5.1
> X-AspNet-Version:4.0.30319
> X-AspNetMvc-Version:3.0
> X-Powered-By:ASP.NET

Update

I've stripped all the code down to this and still no go...

Action:

public FileETagActionResult GetImage()
{
    return new FileETagActionResult();
}

ActionResult:

    public class FileETagActionResult : ActionResult
    {

        public override void ExecuteResult(ControllerContext context)
        {

            byte[] result;

            using (var client = new WebClient())
            {
                result = client.DownloadData("http://myintranet/images/logo.png");
            }

            var hash = MD5.Create().ComputeHash(result);
            string etag = String.Format("\"{0}\"", Convert.ToBase64String(hash));

            TimeSpan expireTs = TimeSpan.FromDays(5);

            context.HttpContext.Response.Cache.SetCacheability(HttpCacheability.Private);
            context.HttpContext.Response.Cache.SetETag(etag);
            context.HttpContext.Response.Cache.SetExpires(DateTime.Now.AddDays(5));
            context.HttpContext.Response.Cache.SetMaxAge(expireTs);

            context.HttpContext.Response.ContentType = "image/png";
            context.HttpContext.Response.BinaryWrite(result);


        }
    }


The ETag will be suppressed if you use HttpCacheability.Private.

You can find more information on this question

If you change it to HttpCacheability.ServerAndPrivate it should work


BZ,

try doing this stuff in the ExcecuteResult override as it's too late by the time the ActionResult is being thrown back (an example from a project that i quickly opened, edit to suit):

public override void ExecuteResult(ControllerContext context)
{
    var textWriter = new StringWriter();
    var viewResult = GetViewResult(textWriter);
    viewResult.ExecuteResult(context);

    var result = textWriter.ToString()
        .RegexReplace("<script.*?>", string.Empty)
        .Replace("</script>", string.Empty);

    //#if RELEASE
    //context.HttpContext.Response.CacheControl = "Public";
    //context.HttpContext.Response.Expires = CacheDuration;
    string version = "1.0"; //your dynamic version number
    HttpCachePolicyBase cache = context.HttpContext.Response.Cache;
    TimeSpan expireTs = TimeSpan.FromDays(CacheDuration);
    cache.SetCacheability(HttpCacheability.Private);
    cache.SetETag(version);
    cache.SetExpires(DateTime.Now.Add(expireTs));
    cache.SetMaxAge(expireTs);
   //#endif

    context.HttpContext.Response.ContentType = "text/javascript";
    context.HttpContext.Response.Write(result);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜