开发者

How is a file served when requested in css :hover as a background image

I have a custom httpHandler in my ASP.NET MVC application that is to be executed w开发者_如何转开发henever an image is requested. If I have a css definition like this:

div#cssSwitch
{
    background-image: url('/Content/themes/base/images/a.png');
}

during load of the page the handler is executed. However, I also have this piece of css

div#cssSwitch:hover
{
    background-image: url('/Content/themes/base/images/b.png');
}

but the handler is never executed for this image. Not during load of the page, not after hovering above the element. Why?

EDIT

My handler is empty so far. I am debugging it locally with breakpoint for the application to break when the handler is executed.

So far it seems the image on :hover has been cached. When cache is deleted, it works as expected. However, I would prefer a way to deny caching of the image. Is there something?

Regards, Trim.


Because hovering event is client-side. And once the image is loaded on first request browser might be caching it. So your handler is not executed on subsequent request.


The browser uses "normal" GET, and should pay attention to the HTTP headers as it does for any other image fetch.

To prevent caching send back the appropriate HTTP handlers ("no-cache", etc). It may also be possible to send back a "304 Not Modified" to avoid sending data if possible while still getting the client to "re-request" the image.

However, the image request will only occur once unless the CSS property is changed (e.g. in JavaScript) -- even if caching is disabled. Also, CSS doesn't "execute" when a style is applied; the resources are merely what they are. This means that the browser can -- and likely does -- load all the url() resources in the CSS before the particular rule is ever applied. The actual load order/timing is unspecified AFAIK but eager loading is significantly easier and more consistent.

As pointed above, using a dynamic property set in JS may be able to get the browser to re-fetch the resource per the GET rules, but at this point trying to use CSS at all for this purpose may be questionable.

Happy coding.


CSS expresions like :Hover, expects to find the file it points to, there is no extra work needed.

in your mentioned case, and assuming that your handler can handle requests to Images, you can provide this file as a full url, and so, the handler will take the lead and serve the file.

so instead of:

div#cssSwitch:hover
{
    background-image: url('/Content/themes/base/images/b.png');
}

it should be:

div#cssSwitch:hover
{
    background-image: url('http://www.MY_WEB_SITE.com/Content/themes/base/images/b.png');
}


This is most likely due to the fact your browser has cached the image on the first page load and so is retrieving the image from the local cache when you next view or refresh your page.

You could try a hard refresh, usually by holding the ctrl key and pressing F5.

If you want to stop caching more permanently then you could use

Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
Response.Cache.SetValidUntilExpires(false);
Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetNoStore();

Take a look at this answer or this answer for more information of how to create a custom attribute.


If you're not using a controller to serve the image you'll have to set up the caching in the IIS.

If you're using a controller to serve the image, you can use decorate the action/controller with this attribute

[Cache(Duration=0)]
public ActionResult Image(string imageName)
{
    // return the image
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class CacheAttribute : ActionFilterAttribute
{
    public CacheAttribute()
    {
        Duration = 10;
    }

    /// <summary>
    /// Gets or sets the cache duration in seconds. The default is 10 seconds.
    /// </summary>
    /// <value>The cache duration in seconds.</value>
    public int Duration
    {
        get;
        set;
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (Duration <= 0) return;

        HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
        TimeSpan cacheDuration = TimeSpan.FromSeconds(Duration);

        cache.SetCacheability(HttpCacheability.Public);
        cache.SetExpires(DateTime.Now.Add(cacheDuration));
        cache.SetMaxAge(cacheDuration);
        cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜