Реализация поддержки ETag в ASP.NET MVC4 WebAPI

17

В последней бета-версии ASP.NET MVC4, как бы вы поддерживали условную поддержку GET через ETags? ActionFilter должен будет иметь возможность выполнить запрос на создание ETag для возвращаемого ресурса, чтобы сравнить с заголовком If-None-Match в запросе. И тогда, независимо от того, был ли входящий ETag в заголовке If-None-Match таким же, как сгенерированный ETag, добавьте сгенерированный ETag в заголовок ответа ETag. Но с ASP.NET MVC4 я понятия не имею, с чего начать. Любые предложения?

    
задан Bullines 28.04.2012 в 19:06
источник

4 ответа

16

Лично я не поклонник «магии фреймов» и предпочитаю простой старый код в веб-методах, иначе мы получим нечто более похожее на WCF, yuk.

Итак, в вашем методе Get web вручную создайте ответ так:

var response = this.Request.CreateResponse(HttpStatusCode.OK, obj);
string hash = obj.ModifiedDate.GetHashCode().ToString();

response.Headers.ETag =
    new EntityTagHeaderValue(String.Concat("\"", hash, "\""), true);

return response;

Обратите внимание, что ETag, созданный из хэш-кода временной метки, является просто иллюстрацией слабой системы тегов. Он также показывает необходимые дополнительные кавычки.

    
ответ дан Luke Puplett 04.07.2012 в 17:27
9

В WebApiContrib есть файл ETagMessageHandler, который делает то, что вам нужно.

UPDATE

Я реализовал кеширование на стороне сервера RFC 2616 в WebApiContrib. Посмотрите на CachingHandler. Подробнее здесь .

Больше обновлений

Это будет активно развиваться и расширяться под CacheCow . Это будет включать как клиентские, так и серверные компоненты. Скоро будут опубликованы пакеты NuGet в ближайшее время .

CachingHandler WebApiContrib будет поддерживаться так, чтобы любые ошибки или проблемы, пожалуйста, дайте мне знать.

    
ответ дан Aliostad 04.05.2012 в 15:21
4

Ответ Луки Пуллетта заставил меня на правильном пути (+1), но обратите внимание, что вам также нужно прочитать ETag на стороне сервера, чтобы не отправлять все данные с каждым запросом:

string hash = obj.ModifiedDate.GetHashCode().ToString();
var etag = new EntityTagHeaderValue(String.Concat("\"", hash, "\""), true);

if (Request.Headers.IfNoneMatch.Any(h => h.Equals(etag)))
{
    return new HttpResponseMessage(HttpStatusCode.NotModified);
}

var response = this.Request.CreateResponse(HttpStatusCode.OK, obj);
response.Headers.ETag = etag;
return response;

Также неплохо было бы уважать заголовок If-Modified-Since . См. RFC 2616 .

    
ответ дан Greg McCoy 14.12.2015 в 23:25
0

Кажется, это то, что вы ищете (см. раздел «Поддержка ETags»):

Ссылка

Если ваша модель хранится глубже в домене и вы не можете применить атрибут [ConcurrencyCheck], вы можете сделать это с помощью ODataModelBuilder:

ODataModelBuilder builder = new ODataConventionModelBuilder();
var myEntity = builder.EntitySet<MyEntity>("MyEntities"); 
myEntity.EntityType.Property(l => l.Version).ConcurrencyToken = true;

это приведет к добавлению свойства «@ odata.etag» в тело ответа.

    
ответ дан Stas Natalenko 27.09.2014 в 20:14