Я задал почти тот же вопрос для меня несколько месяцев назад. Мой ответ я опишу на примере моей реализации.
На стороне сервера у меня есть служба WFC, которая получает запросы в одной из следующих форм
GET /Service/RequestedData?param1=data1¶m2=data2…
GET /Service/RequestedData/IdOfData?param1=data1¶m2=data2…
PUT /Service/RequestedData/IdOfData // with param1=data1¶m2=data2… in body
POST /Service/RequestedData/IdOfData // with param1=data1¶m2=data2… in body
DELETE /Service/RequestedData/IdOfData
Таким образом, запросы находятся в REST для, но GET
запросы имеют некоторые необязательные параметры. Особенно эта часть является портом вашего интереса.
Поскольку WFC поддерживает шаблоны URL, прототип функций, отвечающих на запрос клиента, выглядит как
[WebGet (UriTemplate = "RequestedData?param1={myParam1}¶m2={myParam2}",
ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
MyResult GetData (string myParam1, int myParam2);
Все запросы, как
GET /Service/RequestedData?param1=¶m2=data2
GET /Service/RequestedData?param2=data2¶m1=
GET /Service/RequestedData?param2=data2
будет сопоставлен с тем же вызовом со стороны моей службы WCF. Так что у меня на одну проблему меньше.
Теперь в начале реализации каждого метода, ответ на HTTP GET
запрос я задаю в заголовке HTTP " Cache-Control: max-age = 0 ". Это означает, что клиент всегда пытается проверить кэш браузера клиента, и никакие запросы ajax
не будут легко отвечать из локального кэша, как это может сделать Internet Explorer.
Далее я всегда вычисляю ETag
на основе моих данных. Точный алгоритм является предметом отдельного обсуждения, но важно то, что во всех ответах на HTTP GET
запросы существуют ETag
в заголовке HTTP.
Таким образом, клиенты каждый раз проверяют свой локальный кеш и отправляют GET-запрос на сервер. Они отправляют ETag
из локального кэша внутри HTTP-заголовка "If-None-Match
". Сервер вычисляет ETag
, в котором есть данные, которые будут отправляться обратно на этот запрос GET. Это ETag
данных, таких же, как на клиентском сервере запросов отправлять ответный ответ с пустым телом и кодом «304 Not Modified
» назад. В этом случае браузер выдает данные из локального кэша.
Если тот же клиент по неизвестной причине создаст новую версию запроса URL, которая будет интерпретироваться из веб-браузера как новый URL-адрес, тогда веб-браузер не найдет старый ответ сервера в локальном кэшируйте и отправьте еще один и тот же запрос на сервер. Это настоящая проблема? Сервер отправляет данные еще раз. Если у вас есть кэширование на стороне сервера, вы можете сделать немного больше оптимизации. В большинстве случаев URL-адрес GET-запросов будет создаваться клиентским JavaScript, поэтому у вас никогда не будет такой ситуации.
Вычисление ETag
и установка заголовков "Cache-Control: max-age=0
" и Etag
, а также установка кода "304 Not Modified
" должны выполнять функцию WFC, но это очень просто.
Самое важное, что моя реализация вычисления ETag
не так обширна, как получение целых данных с сервера базы данных и отсюда кеша MD5 для вычислений. Я постоянно использую rowversion
тип данных в каждой строке данных в базе данных SQL Server. Этот rowversion
является ничем иным, как счетчиком изменений в базе данных. При изменении строки данных rowversion
значение в соответствующей строке будет увеличиваться. Таким образом, если сделать оператор SELECT
из максимального значения rowversion
, и это значение не изменилось по сравнению с предыдущими запросами, можно быть уверенным, что данные не изменились за период времени. Алгоритм расчета ETa
g должен быть чувствителен только к удалению данных из таблицы. Но это тоже решенная проблема. Еще немного об этом вы можете прочитать в Обработка параллелизма транзакции Sql .
Я не хочу предлагать мой ETag
расчет как лучший выбор, я только хочу сказать, что вычисление ETag
может быть намного дешевле, чем вычисление MD5 из всех данных.
В случае ошибок Сервер выдает исключение, которое будет сопоставлено с HTTP-кодом, который я определю в операторе throw. В качестве тела WFC отправляет стандартный объект JSON {"description":"My error text"}
. Также возможен пользовательский объект ошибки (см. Включено ли исключение WebProtocolException в .net 4.0? ). На стороне клиента я использую jQuery, и в соответствующем jQuery.ajax
внутри обработчика события ошибки сообщение об ошибке будет декодировано и отображено пользователю.
Итак, моя рекомендация: использовать ETag
вместе с "Cache-Control: max-age=0
" для всех запросов HTTP GET
. Для всех остальных запросов я рекомендую вам внедрить сервис RESTfull . Для реализации ошибки вы должны взглянуть на самый родной путь, который поддерживается программным обеспечением, используемым для реализации сервера и клиента, и использовать это.
ОБНОВЛЕНО : Чтобы очистить структуру URL, я должен добавить следующее. В моем сервисе основная часть, такая как GET /Service/RequestedData/IdOfData
, описывает запрашиваемые объекты данных. Параметры param1=data1¶m2=data2
в основном соответствуют информации о сортировке , пейджинге и фильтрации данных. Я использую активный плагин jqGrid для jQuery, и если конечный пользователь прокручивает сетку до следующей страницы, нажимает на заголовок столбца (сортировка данных) или, если он устанавливает фильтр в отношении функции поиска, все это следует для различных дополнительных к параметрам добавлен основной URL.