Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cache output of action method that returns image to the view in asp.net mvc?

I've read lots of posts about caching already, but none of them actually match my needs exactly. In my mvc 3 app I have an action method GetImage() that returns a File of image type. Then I use this method in a view to display image:

<img width="75" height="75" src="@Url.Action("GetImage", "Store", new {productId = item.ProductId})"/>

I want to cache images on a Server. So, what I've already tried:

1) to use OutputCacheAttribute:

    [HttpGet, OutputCache(Duration = 10, VaryByParam = "productId", Location = OutputCacheLocation.Server, NoStore = true)]
    public FileContentResult GetImage(int productId)
    {
        var p = _productRepository.GetProduct(productId);
        if (p != null)
        {
            if (System.IO.File.Exists(GetFullProductImagePath(productId)))
            {
                var image = Image.FromFile(GetFullProductImagePath(productId));
                return File(GetFileContents(image), "image/jpeg");
            }
        }
        var defaultPath = AppDomain.CurrentDomain.BaseDirectory +
                             ConfigurationManager.AppSettings["default-images-directory"];

        var defaultImage = Image.FromFile(Path.Combine(defaultPath, "DefaultProductImage.jpg"));
        return File(GetFileContents(defaultImage), "image/jpeg");
    }

Images are not cached (I get status: 200 OK)

2) to use the following Response.Cache methods in a GetImage() method:

    public FileContentResult GetImage(int productId)
    {
        Response.Cache.SetCacheability(HttpCacheability.Public);
        Response.Cache.SetMaxAge(new TimeSpan(0, 0, 0, 10));
        Response.Cache.SetExpires(DateTime.Now.Add(new TimeSpan(0, 0, 0, 10)));
        Response.Cache.AppendCacheExtension("must-revalidate, proxy-revalidate");        
        // other code is the same
    }

Images are not cached

3) Here I get: 304 Not Modified, but the GetImage() method returns nothing (empty image)

    public FileContentResult GetImage(int productId)
    {
        Response.StatusCode = 304;
        Response.StatusDescription = "Not Modified";
        Response.AddHeader("Content-Length", "0");     
        // other code is the same
    }

Question: How to cache the output of this action method on a server?

like image 228
Aleksei Chepovoi Avatar asked Feb 08 '13 09:02

Aleksei Chepovoi


1 Answers

Try like this:

[HttpGet]
[OutputCache(
    Duration = 10, 
    VaryByParam = "productId", 
    Location = OutputCacheLocation.ServerAndClient)]
public ActionResult GetImage(string productId)
{
    ...
}

Things to notice: using OutputCacheLocation.ServerAndClient and gotten rid of NoStore = true.

like image 183
Darin Dimitrov Avatar answered Sep 19 '22 13:09

Darin Dimitrov