0

Code from How to show image in jqgrid in edit mode is used to show images in jqgrid.

If row is updated (edit action is controller is called), row image is changed in server: image url remains same but new image is returned from server after row save.

jqgrid still shows old image: it does not request new image from server. Pressing grid refresh button also does not request new image. Pressing browser refresh button retrieves new image but this is very inconvenient.

How to show new image after row is updated in jqgrid ?

Update

I added outputcache attribute as Oleg recommends. Using fiddler I verifed that image response header from image call

GET http://localhost:50076/erp/Grid/GetImage?_entity=Artpilt&size=54&id=734 HTTP/1.1
Accept: image/png, image/svg+xml, image/*;q=0.8, */*;q=0.5
Referer: http://localhost:50076/erp/Grid?_entity=Artpilt
Accept-Language: et-EE
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: localhost:50076
If-Modified-Since: Mon, 03 Oct 2011 11:25:29 GMT
If-None-Match: "ArtPilt734"
Connection: Keep-Alive
Cookie: .MyAuth=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

is:

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Mon, 03 Oct 2011 11:17:46 GMT
X-AspNet-Version: 2.0.50727
X-AspNetMvc-Version: 2.0
Cache-Control: public, max-age=0, s-maxage=0
Expires: Mon, 03 Oct 2011 11:17:46 GMT
Last-Modified: Mon, 03 Oct 2011 11:17:46 GMT
ETag: "ArtPilt734"
Content-Type: image/jpeg
Content-Length: 1444
Connection: Close

If data in edit form is changed and saved, old image still remains. fiddler shows that tmage is not retrieved from server.

If edit form is closed, old image is shown in grid. Pressing jqgrid refresh button in jqgrid toolbar causes old image still to be displayed. Fiddler shows that new image request is not is not read from server. Only pressing F5 in browser retrieves new image.

How to refresh image immediately if row data is changed in edit form ?

Update2 I think Oleg means HttpCacheability.NoCache , not HttpCacheability.Private as he wrote in comment.

I changed MVC2 controller to

    [OutputCache(Duration = 0, VaryByParam = "")]
    public FileContentResult GetImage(string _entity, int id, int? size)
    {
        HttpContext.Response.Cache.SetExpires(DateTime.Now.AddDays(-1));
        Response.Cache.SetCacheability(HttpCacheability.NoCache);
        Response.Cache.SetMaxAge(new TimeSpan(0));

        ... retrieving image and fileextension form database skipped ...
        HttpContext.Response.Cache.SetETag("\"ArtPilt" + id.ToString() + "\"");
        return File(image, "image/" + imagetype );
    }

respose header is

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Mon, 03 Oct 2011 13:10:35 GMT
X-AspNet-Version: 2.0.50727
X-AspNetMvc-Version: 2.0
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Content-Type: image/jpeg
Content-Length: 1457
Connection: Close

but problem persists. Fiddler shows that current row image is not retrieved.

Community
  • 1
  • 1
Andrus
  • 26,339
  • 60
  • 204
  • 378
  • If you use Firebug or another web debugger and investigate the HTML of your grid after saving the row, do you see the URL of the new image in the IMG element? – Walter Stabosz Oct 03 '11 at 11:17
  • @Walter: URL is the same always. As shown in updated answer this is dynamic url containing row id. GetImage returns different images from same url. GetImage examines row data and returns image depending on row data. There is actually image column in row which is changed if row data has changed. Getimage returns this row column value from database – Andrus Oct 03 '11 at 11:38

1 Answers1

0

It sounds like caching problem. You should set Cache-Control: max-age=0 in HTTP header of the GetImage action. You can consider to set ETag additionally. See this answer for more information.

In ASP.NET MVC program you can use OutputCache attribute

[OutputCache (Duration = 0, VaryByParam = "")]

or

Response.Cache.SetCacheability (HttpCacheability.Public);
Response.Cache.SetMaxAge (new TimeSpan (0));

or something like

Response.AddHeader ("Cache-Control", "max-age=0");

UPDATED: I used HttpContext.Current.Response.Cache.SetMaxAge (new TimeSpan (0)); in one demo project which generate Chat used in the <img src=...>. The HTTP header will be

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Mon, 03 Oct 2011 11:59:40 GMT
X-AspNet-Version: 4.0.30319
X-AspNetMvc-Version: 2.0
Cache-Control: private, max-age=0
Content-Type: image/png
Content-Length: 55420
Connection: Close

and the corresponding action which generate and provide image will be called every time. The Expires header from the HTTP response which you posted looks suspected for me. I don't have it.

Community
  • 1
  • 1
Oleg
  • 220,925
  • 34
  • 403
  • 798
  • I thought if it were a browser cache issue, the HTTP request would still get called, except that once the browser read the response header and realized that it had a cached copy of the image, the transfer would end. – Walter Stabosz Oct 03 '11 at 11:14
  • @Oleg: thank you very much. I added cache directive as you suggested but problem persists. I updated question. – Andrus Oct 03 '11 at 11:35
  • @Walter Stabosz: I don't think that you are right. All depends on default HTTP headers used in the site. For example, if you open [the demo](http://www.ok-soft-gmbh.com/jqGrid/SimpleLocalGridWithImages.htm) from the previous answer and examine HTTP traffic with respect of [Fiddler](http://www.fiddler2.com/fiddler2/) of [Firebug](http://getfirebug.com/) you will see that **no HTTP requests** will be send if one opens edit form in IE. – Oleg Oct 03 '11 at 11:39
  • @Andrus: I think you should remove `Expires` HTTP header or set it to the date from the past. You can use `SetExpires`. Moreover probably the line `Response.Cache.SetCacheability (HttpCacheability.Public);` should be better removed to set `Cache-Control: private` and disable Image caching on the proxy (if any exist). – Oleg Oct 03 '11 at 11:49
  • @Andrus: I don't have exactly your case, but in very close case which I described in **UPDATED** part of my answer I have no problems which you described. – Oleg Oct 03 '11 at 12:16
  • @Oleg. Thank you. I think you meant `HttpCacheability.NoCache` . I added all changed you recommended but problem persists. I updated question. I can create live testcase if somebody is interested. i'm running it from visual studio in localhost, fiddler is only proxy – Andrus Oct 03 '11 at 13:44
  • @Andrus: The usage of `Response.Cache.SetMaxAge (new TimeSpan (0));` **without** explicitly set of `Response.Cache.SetCacheability (HttpCacheability.Public)` already place `Cache-Control: private, max-age=0` in the header. If you have live demo I could look at this. – Oleg Oct 03 '11 at 14:19
  • @Oleg. Thank you. I send you testcase by e-mail. – Andrus Oct 03 '11 at 16:59
  • @Oleg, did you received the testcase ? – Andrus Oct 24 '11 at 15:12
  • @Andrus: stackoverflow is the place to provide questions and answers which can have *value for other people*. The testcase which you send seems be *your* solution which is relatively complex. I don't see that the testcase has any value for other. The stackoverflow is not the place where you receive free support for every your problem. You should analyse the problem yourself and reduce it to clear and small problem which can be formulated as the question on the stackoverflow. – Oleg Oct 24 '11 at 16:19