2009-03-02 44 views
13

如您所知,我们在RC1版本的ASP.NET MVC中有一个新的ActionResult调用FileResult如何使用ASP.NET MVC中的FileResult返回304状态RC1

使用它,您的动作方法可以动态地将图像返回给浏览器。事情是这样的:

public ActionResult DisplayPhoto(int id) 
{ 
    Photo photo = GetPhotoFromDatabase(id); 
    return File(photo.Content, photo.ContentType); 
} 

在HTML代码中,我们可以使用这样的事情:

<img src="http://mysite.com/controller/DisplayPhoto/657"> 

由于图像动态返回,我们需要一种方法来缓存返回的流,让我们不要不需要从数据库中再次读取图像。我想我们可以这样做,我不知道:

Response.StatusCode = 304; 

这告诉浏览器,您已经在缓存中有图像。在将StatusCode设置为304之后,我只是不知道要在我的操作方法中返回什么内容。我应该返回null还是什么?

回答

8

不要对FileResult使用304。从the spec

304响应必须不包含一个 消息体,且因此是总是通过 头字段之后的第一空行 终止。

目前还不清楚你试图从你的问题中做什么。服务器不知道浏览器在其缓存中有什么。浏览器决定。如果您试图告诉浏览器在需要时再次获取图像(如果图像已经有副本),请设置响应Cache-Control header

如果您需要返回304,请改为使用EmptyResult。

+0

在第一请求,我设置ETag的属性这样的: HttpContext.Current.Response.Cache.SetETag(someUniqueValue); 在随后的请求中,通过阅读ETag,我知道图像在浏览器的缓存中,因此我必须返回304 – Meysam 2009-03-03 08:54:03

+0

返回304时使用EmptyResult,而不是FileResult。 – 2009-03-03 12:41:27

25

这个博客回答了我的问题; http://weblogs.asp.net/jeff/archive/2009/07/01/304-your-images-from-a-database.aspx

基本上,您需要读取请求标头,比较最后修改日期并返回304(如果它们匹配),否则返回图像(具有200状态)并适当设置缓存标头。从博客

代码片段:

public ActionResult Image(int id) 
{ 
    var image = _imageRepository.Get(id); 
    if (image == null) 
     throw new HttpException(404, "Image not found"); 
    if (!String.IsNullOrEmpty(Request.Headers["If-Modified-Since"])) 
    { 
     CultureInfo provider = CultureInfo.InvariantCulture; 
     var lastMod = DateTime.ParseExact(Request.Headers["If-Modified-Since"], "r", provider).ToLocalTime(); 
     if (lastMod == image.TimeStamp.AddMilliseconds(-image.TimeStamp.Millisecond)) 
     { 
      Response.StatusCode = 304; 
      Response.StatusDescription = "Not Modified"; 
      return Content(String.Empty); 
     } 
    } 
    var stream = new MemoryStream(image.GetImage()); 
    Response.Cache.SetCacheability(HttpCacheability.Public); 
    Response.Cache.SetLastModified(image.TimeStamp); 
    return File(stream, image.MimeType); 
} 
0

在MVC中的新版本,你会更好返回一个HttpStatusCodeResult。这样你就不需要设置Response.StatusCode或者其他任何东西。

public ActionResult DisplayPhoto(int id) 
{ 
    //Your code to check your cache and get the image goes here 
    //... 
    if (isChanged) 
    { 
     return File(photo.Content, photo.ContentType); 
    } 
    return new HttpStatusCodeResult(HttpStatusCode.NotModified); 
}