How can I use output caching with a .ashx handler? In this case I'm doing some heavy image processing and would like the handler to be cached for a minute or so.
Also, does anyone have any recommendations on how to prevent dogpiling?
There are some good sources but you want to cache you processing server side and client-side.
Adding HTTP headers should help in the client side caching
here are some Response headers to get started on..
You can spend hours tweaking them until you get the desired performance
//Adds document content type
context.Response.ContentType = currentDocument.MimeType;
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetExpires(DateTime.Now.AddMinutes(10));
context.Response.Cache.SetMaxAge(new TimeSpan(0,10,0));
context.Response.AddHeader("Last-Modified", currentDocument.LastUpdated.ToLongDateString());
// Send back the file content
context.Response.BinaryWrite(currentDocument.Document);
As for server side caching that is a different monster... and there are plenty of caching resources out there...
you can use like this
public class CacheHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
OutputCachedPage page = new OutputCachedPage(new OutputCacheParameters
{
Duration = 60,
Location = OutputCacheLocation.Server,
VaryByParam = "v"
});
page.ProcessRequest(HttpContext.Current);
context.Response.Write(DateTime.Now);
}
public bool IsReusable
{
get
{
return false;
}
}
private sealed class OutputCachedPage : Page
{
private OutputCacheParameters _cacheSettings;
public OutputCachedPage(OutputCacheParameters cacheSettings)
{
// Tracing requires Page IDs to be unique.
ID = Guid.NewGuid().ToString();
_cacheSettings = cacheSettings;
}
protected override void FrameworkInitialize()
{
// when you put the <%@ OutputCache %> directive on a page, the generated code calls InitOutputCache() from here
base.FrameworkInitialize();
InitOutputCache(_cacheSettings);
}
}
}
Old, question but the answer didn't really mentioned the server-side handling.
As in the winning answer, I would use this for the client side
:
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetExpires(DateTime.Now.AddMinutes(10));
context.Response.Cache.SetMaxAge(TimeSpan.FromMinutes(10));
and for the server side
, since you are using a ashx instead of a web page, I'm assuming that you are directly writing the output to the Context.Response
.
In that case you could use something like this (in this case I want to save the response based on parameter "q", and Im using a sliding window expiration)
using System.Web.Caching;
public void ProcessRequest(HttpContext context)
{
string query = context.Request["q"];
if (context.Cache[query] != null)
{
//server side caching using asp.net caching
context.Response.Write(context.Cache[query]);
return;
}
string response = GetResponse(query);
context.Cache.Insert(query, response, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(10));
context.Response.Write(response);
}
I used the following with success and thought it worthwhile to post here .
Manually controlling the ASP.NET page output cache
From http://dotnetperls.com/cache-examples-aspnet
Setting cache options in Handler.ashx files
First, you can use HTTP handlers in ASP.NET for a faster way to server dynamic content than Web Form pages. Handler.ashx is the default name for an ASP.NET generic handler. You need to use the HttpContext parameter and access the Response that way.
Sample code excerpted:
<%@ WebHandler Language="C#" Class="Handler" %>
C# to cache response for 1 hour
using System;
using System.Web;
public class Handler : IHttpHandler {
public void ProcessRequest (HttpContext context) {
// Cache this handler response for 1 hour.
HttpCachePolicy c = context.Response.Cache;
c.SetCacheability(HttpCacheability.Public);
c.SetMaxAge(new TimeSpan(1, 0, 0));
}
public bool IsReusable {
get {
return false;
}
}
}
The solution with the OutputCachedPage works fine, however at a price of the performance, since you need to instantiate an object derived from the System.Web.UI.Page base class.
A simple solution would be to use the Response.Cache.SetCacheability, as suggested by some of the above answers. However for the response to be cached at the server (inside Output Cache) one needs to use HttpCacheability.Server, and set a VaryByParams or VaryByHeaders (note that when using VaryByHeaders URL can't contain a query string, since the cache will be skipped).
Here's a simple example (based on https://support.microsoft.com/en-us/kb/323290):
<%@ WebHandler Language="C#" Class="cacheTest" %>
using System;
using System.Web;
using System.Web.UI;
public class cacheTest : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
TimeSpan freshness = new TimeSpan(0, 0, 0, 10);
DateTime now = DateTime.Now;
HttpCachePolicy cachePolicy = context.Response.Cache;
cachePolicy.SetCacheability(HttpCacheability.Public);
cachePolicy.SetExpires(now.Add(freshness));
cachePolicy.SetMaxAge(freshness);
cachePolicy.SetValidUntilExpires(true);
cachePolicy.VaryByParams["id"] = true;
context.Response.ContentType = "application/json";
context.Response.BufferOutput = true;
context.Response.Write(context.Request.QueryString["id"]+"\n");
context.Response.Write(DateTime.Now.ToString("s"));
}
public bool IsReusable
{
get
{
return false;
}
}
}
Hint: you monitor the caching in the Performance Counters "ASP.NET Applications__Total__\Output Cache Total".
来源:https://stackoverflow.com/questions/1109768/how-to-use-output-caching-on-ashx-handler