Установить ETag для FileResult - MVC 3 - PullRequest
8 голосов
/ 17 февраля 2011

MVC 3 RTM. У меня есть действие, которое возвращает файл (изображение / JPEG). Я пытаюсь установить ETag для файла без успеха (etag не проходит через заголовок). Я пробовал оба Response.Cache.SetETag и Response.AppenderHeader. Если я добавлю свой собственный тег заголовка, он будет работать, как и ожидалось, это просто ETag, который я не могу установить.

Вот источник.

        [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");
        }

А вот ресурс запроса / ответа:

> Request
> URL:http://localhost/MyApp/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

Обновление

Я сократил весь код до этого и до сих пор не могу ...

Действие:

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);


        }
    }

Ответы [ 2 ]

10 голосов
/ 07 марта 2011

ETag будет подавлен, если вы используете HttpCacheability.Private.

Вы можете найти больше информации по этому вопросу

Если вы измените его на HttpCacheability.ServerAndPrivate, оно должно работать

1 голос
/ 17 февраля 2011

BZ

попробуйте сделать это в переопределении ExcecuteResult, так как уже слишком поздно к моменту возврата ActionResult (пример из проекта, который я быстро открыл, отредактируйте в соответствии с требованиями):

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);
}
...