asp.net - Cómo utilizar el almacenamiento en caché de resultados en el controlador.ashx
caching (5)
¿Cómo puedo usar el almacenamiento en caché de salida con un controlador .ashx? En este caso, estoy realizando un procesamiento de imagen pesado y me gustaría que el controlador se guarde en caché durante aproximadamente un minuto.
Además, ¿alguien tiene alguna recomendación sobre cómo evitar el dogpiling?
Hay algunas buenas fuentes, pero desea almacenar en caché su procesamiento del lado del servidor y del lado del cliente.
Agregar encabezados HTTP debería ayudar en el almacenamiento en caché del lado del cliente
aquí hay algunos encabezados de respuesta para comenzar.
Puedes pasar horas ajustándolos hasta obtener el rendimiento deseado
//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);
En cuanto al almacenamiento en caché del lado del servidor que es un monstruo diferente ... y hay muchos recursos de almacenamiento en caché por ahí ...
La solución con OutputCachedPage funciona bien, sin embargo a un precio del rendimiento, ya que necesita crear una instancia de un objeto derivado de la clase base System.Web.UI.Page .
Una solución simple sería usar Response.Cache.SetCacheability , como lo sugieren algunas de las respuestas anteriores. Sin embargo, para que la respuesta se almacene en caché en el servidor (dentro de Caché de resultados), se necesita usar HttpCacheability.Server y establecer un VaryByParams o VaryByHeaders (tenga en cuenta que al usar VaryByHeaders URL no puede contener una cadena de consulta, ya que se omitirá el caché )
Aquí hay un ejemplo simple (basado en 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;
}
}
}
Sugerencia: supervisa el almacenamiento en caché en los contadores de rendimiento "Aplicaciones ASP.NET__Total __ / Total de caché de salida".
Usé lo siguiente con éxito y pensé que valía la pena publicar aquí.
Controlar manualmente el caché de salida de la página ASP.NET
Desde http://dotnetperls.com/cache-examples-aspnet
Establecer opciones de caché en archivos Handler.ashx
En primer lugar, puede usar manejadores HTTP en ASP.NET para obtener una forma más rápida de contenido dinámico del servidor que las páginas Web Form. Handler.ashx es el nombre predeterminado para un controlador genérico de ASP.NET. Necesita usar el parámetro HttpContext y acceder a la respuesta de esa manera.
Ejemplo de código extraído:
<%@ WebHandler Language="C#" Class="Handler" %>
C # para guardar en caché la respuesta durante 1 hora
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;
}
}
}
Viejo, pregunta pero la respuesta realmente no mencionó el manejo del lado del servidor.
Como en la respuesta ganadora, usaría esto para el client side
:
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetExpires(DateTime.Now.AddMinutes(10));
context.Response.Cache.SetMaxAge(TimeSpan.FromMinutes(10));
y para el server side
, dado que está utilizando un ashx en lugar de una página web, supongo que está escribiendo directamente el resultado en Context.Response
.
En ese caso, podría usar algo como esto (en este caso, quiero guardar la respuesta en función del parámetro "q", y estoy usando un vencimiento de ventana deslizante)
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);
}
puedes usar esto
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);
}
}
}