Wie zu verwenden ETag in Web-API über die Aktion filter zusammen mit HttpResponseMessage
Habe ich eine ASP.Net Web-API-controller, die einfach liefert die Liste der Benutzer.
public sealed class UserController : ApiController
{
[EnableTag]
public HttpResponseMessage Get()
{
var userList= this.RetrieveUserList(); //This will return list of users
this.responseMessage = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ObjectContent<List<UserViewModel>>(userList, new JsonMediaTypeFormatter())
};
return this.responseMessage;
}
}
und eine Aktion filter-Attribut class EnableTag
die dafür verantwortlich ist, zu verwalten ETag und cache :
public class EnableTag : System.Web.Http.Filters.ActionFilterAttribute
{
private static ConcurrentDictionary<string, EntityTagHeaderValue> etags = new ConcurrentDictionary<string, EntityTagHeaderValue>();
public override void OnActionExecuting(HttpActionContext context)
{
if (context != null)
{
var request = context.Request;
if (request.Method == HttpMethod.Get)
{
var key = GetKey(request);
ICollection<EntityTagHeaderValue> etagsFromClient = request.Headers.IfNoneMatch;
if (etagsFromClient.Count > 0)
{
EntityTagHeaderValue etag = null;
if (etags.TryGetValue(key, out etag) && etagsFromClient.Any(t => t.Tag == etag.Tag))
{
context.Response = new HttpResponseMessage(HttpStatusCode.NotModified);
SetCacheControl(context.Response);
}
}
}
}
}
public override void OnActionExecuted(HttpActionExecutedContext context)
{
var request = context.Request;
var key = GetKey(request);
EntityTagHeaderValue etag;
if (!etags.TryGetValue(key, out etag) || request.Method == HttpMethod.Put || request.Method == HttpMethod.Post)
{
etag = new EntityTagHeaderValue("\"" + Guid.NewGuid().ToString() + "\"");
etags.AddOrUpdate(key, etag, (k, val) => etag);
}
context.Response.Headers.ETag = etag;
SetCacheControl(context.Response);
}
private static void SetCacheControl(HttpResponseMessage response)
{
response.Headers.CacheControl = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromSeconds(60),
MustRevalidate = true,
Private = true
};
}
private static string GetKey(HttpRequestMessage request)
{
return request.RequestUri.ToString();
}
}
Den oben genannten code, erstellen Sie ein Attribut Klasse zur Verwaltung von ETag. Also auf die erste Anforderung, wird eine neue E-Tag und für die nachfolgende Anforderung es wird geprüft, ob jede ETag existierte. wenn dem so ist, wird es erzeugt Not Modified
HTTP-Status und wieder zurück zum client.
Mein problem ist, ich möchte erstellen Sie eine neue ETag wenn es Veränderungen in meinem Benutzer-Liste, ex. ein neuer Benutzer Hinzugefügt oder ein vorhandener Benutzer gelöscht wird. und hängen Sie es mit der Antwort. Dieser kann nachverfolgt werden durch die userList
variable.
Derzeit ist die ETag empfangen von client und server sind die gleichen, die aus jeder 2. Anfrage, so dass in diesem Fall es wird immer generieren Not Modified
status, während ich will es, wenn sich eigentlich nichts geändert.
Kann jemand mich führen, in diese Richtung? Vielen Dank im Voraus.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Meine Anforderung war der cache mein web-api-JSON-Antworten... Und all die Lösungen nicht leicht, "link", wo die Daten generiert werden - sprich in der Steuerung...
Also meine Lösung war die Erstellung einer wrapper "CacheableJsonResult" generiert eine Antwort, und fügte dann den ETag in die Kopfzeile. Dies ermöglicht eine etag übergeben werden, wenn die controller-Methode generiert, und will wieder den Inhalt...
Und dann im controller - Rendite-dieses Objekt:
Müssen Sie definieren, wie Granulat, um Ihre tags, für meine Daten ist user-spezifisch, so dass ich auch die UserId in der CacheKey (etag)
eine gute Lösung für ETag und in ASP.NET Web-API ist die Verwendung CacheCow . Ein guter Artikel ist hier.
Es ist einfach zu bedienen und Sie nicht haben, um ein benutzerdefiniertes Attribut erstellen.
Spaß haben
.u
Fand ich CacheCow sehr aufgebläht, was es bedeutet, wenn der einzige Grund ist, um den Betrag an Daten übertragen, möchten Sie vielleicht so etwas wie dieses:
Nicht einrichten zu müssen nichts, einstellen und vergessen. So wie ich es mag. 🙂
Ich mag die Antwort, die war von @Viezevingertjes. Es ist der eleganteste und "Keine Notwendigkeit für die Einrichtung nichts" - Ansatz ist sehr bequem. Ich mag es auch 🙂
Aber ich denke, es hat ein paar Nachteile:
Es war auch nicht Teil der Frage und niemand erwähnt es. Aber ETag sollte verwendet werden, für die Cache-Validierung. Es sollte daher verwendet werden, mit Cache-Control-header, so dass die clients selbst haben nicht den server aufrufen, bis der cache abläuft (es kann sein sehr kurzen Frist hängt davon ab, Ihre Ressourcen). Wenn der cache abgelaufen ist, dann client stellt eine Anfrage mit ETag und zu validieren. Für mehr details über caching finden Sie in diesem Artikel.
So, dass ist der Grund, warum ich beschlossen, pimp it up ein wenig, aber. Vereinfachte filter-keine Notwendigkeit für OnActionExecuting Methode, funktioniert mit Jeder Antwort Typen, keine Serialisierung. Und vor allem fügt CacheControl-header. Es kann verbessert werden, z.B. mit Public-cache aktiviert ist, usw... Allerdings rate ich dir dringend zu verstehen, caching und ändern Sie es sorgfältig. Wenn Sie HTTPS verwenden, und die Endpunkte, die gesichert sind, dann ist dieses setup in Ordnung sein sollte.
Verwendung e.g: mit 1 min client-side caching:
Scheint ein schöner Weg, es zu tun: