我有一个简单的C#Windows UAP项目,该项目使用HttpClient
在Web服务器上调用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脚本运行正常,但我的应用程序获得的响应与我手动在浏览器中运行脚本时的响应不同。
为什么会这样?
答案 0 :(得分:2)
提供HTTPClient的Windows运行时具有非常积极的搜索策略以节省用户的带宽。除非您的服务器显式设置缓存持续时间标头,否则它将直接从缓存返回所有**请求和相同的Uri,甚至无需联系您的服务器。
您可以通过以下方式关闭此行为:
设置缓存持续时间标头(缓存控制:无缓存等)。
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
看到了,对我的其他人不确定