2009-03-02 80 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); 
}