Почему на моем приложении не отражаются изменения на стороне сервера?

У меня есть простой C # Windows UAP проект, который использует HttpClient вызвать скрипт PHP на веб-сервере. Скрипт возвращает XML-документ, который содержит некоторые GUID (*.xml файлы с расширением опущены, оставив GUID). Мое приложение затем использует эти данные. Если я внесу изменение на сервере, по совпадению заставляя PHP-скрипт возвращать разные данные, мое приложение все еще использует старые данные (если быть точным, оно делает это до тех пор, пока приложение не будет перезапущено). Если вызвать скрипт с помощью браузера, данные появятся так, как я ожидал, но приложение не делает то, что должно с данными. Кажется, что первый ответ кешируется.

Вот пример:
Скажем, я начинаю с одного файла в папке, где мой скрипт PHP находит все файлы * .xml (eef8401a-b5cd-4da7-ad36-0fb7a8fa6c62.xml в этом случае).
Скрипт должен и действительно возвращает:

<?xml version="1.0"?>
<eventlist>
<id>eef8401a-b5cd-4da7-ad36-0fb7a8fa6c62</id>
</eventlist>

Когда я запускаю приложение, его ответ такой же.
Пока все работает как надо.
Однако, скажем, я добавляю новый файл XML в папку (сейчас eee8401a-b5cd-4da7-ad36-0fb7a8fa6c62.xml а также eef8401a-b5cd-4da7-ad36-0fb7a8fa6c62.xml). Сценарий возвращается так, как я ожидал:

<?xml version="1.0"?>
<eventlist>
<id>eee8401a-b5cd-4da7-ad36-0fb7a8fa6c62</id>
<id>eef8401a-b5cd-4da7-ad36-0fb7a8fa6c62</id>
</eventlist>

Ответ приложения на этот раз остается прежним (только с одним id элемент).
Это продолжается до тех пор, пока приложение не перезапустится. После этого все работает как надо — пока я не внесу еще одно изменение в папку.

Вот мой PHP-скрипт:

<?php
header('Content-type: text/xml');
$handler = opendir('C:\path\to\folder\\');
$ids = '';
while (($file = readdir($handler)) !== FALSE) {
if (strpos($file, '.xml') !== FALSE) {
$ids .= '<id>'.str_replace('.xml', '', $file).'</id>';
}
}
closedir($handler);
exit('<eventlist>'.$ids.'</eventlist>');
?>

И код C # моего приложения:

    public static async Task<string> ContactServer(ApiMethod m, IProgress<double[]> prog, params KeyValuePair<string, string>[] args) {
using (var client = new HttpClient()) {
var path = m.ToString().ToLower() + "/"; // in this case, is 'list/'.
//...
// other stuff, omitted for simplicity
//...
var fullUrl = "http://example.com/path/to/api/" + path; // in this case, is 'http://example.com/path/to/api/list/'.
var d = await client.GetAsync(new Uri(fullUrl));
var data = await d.Content.ReadAsStringAsync();
Debug.WriteLine(data);
return data;
}
}

Опять же, мой PHP-скрипт работает нормально, но мое приложение получает другой ответ, чем я, когда запускаю скрипт в своем браузере вручную.
Почему это происходит?

3

Решение

Среда выполнения Windows, которая предоставляет HTTPClient, имеет очень агрессивную стратегию веб-кэширования для экономии полосы пропускания пользователя. Если ваш сервер явно не установит заголовок длительности кэша, он будет возвращать все ** запросы с тем же Uri непосредственно из кэша, даже не связываясь с вашим сервером.

Вы можете отключить это поведение:

Установка заголовка длительности кеша (cache-control: no-cache и т. Д.).

var request = (HttpWebRequest)WebRequest.Create(url.ToString());
if (request.Headers == null)
request.Headers = new WebHeaderCollection();
request.Headers.Add("Cache-Control", "no-cache");

Добавление случайного числа в строку запроса вашего запроса.

string uri = "http://host.com/path?cache=" + Guid.NewGuid().ToString();

Или, как предложил CodeCaster, вы также можете избежать кеширования, используя If-Modified-Since заголовок

HttpWebRequest request = HttpWebRequest.CreateHttp(url);
if (request.Headers == null)
request.Headers = new WebHeaderCollection();
// Make sure that you format time string according RFC.
request.Headers[HttpRequestHeader.IfModifiedSince] = DateTime.UtcNow.ToString("r");

или вы можете добавить к каждому запросу клиента

httpClient.DefaultRequestHeaders.IfModifiedSince = DateTime.UtcNow.ToString("r");

С помощью Windows.Web.Http Вы также можете использовать

var httpFilter = new Windows.Web.Http.Filters.HttpBaseProtocolFilter();
httpFilter.CacheControl.ReadBehavior =
Windows.Web.Http.Filters.HttpCacheReadBehavior.MostRecent;
var httpClient = new Windows.Web.Http.HttpClient(httpFilter);

** Я ответил на все запросы, но я не знаю, если это строго правильно, я посмотрю и проверю и обновлю здесь, хотя CodeCaster предложил GET а также HEAD только; Я конечно видел на GET, неуверенный в других от макушки

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]