C# 为什么异步方法在这里只执行一次HTTP请求?

C# 为什么异步方法在这里只执行一次HTTP请求?,c#,wpf,windows-8.1,windows-store,dotnet-httpclient,C#,Wpf,Windows 8.1,Windows Store,Dotnet Httpclient,简而言之,这是一个Windows应用商店应用程序,在Visual Studio 2013中使用F5运行时无法发出多个HTTP请求。目标平台是Windows 8.1 每次单击按钮时,都会从公共服务器请求时间信息并显示响应。然而,正如Fiddler所示,尽管相关的click事件处理程序被反复运行,但实际的HTTP请求仅在第一次单击时发出 我已经走过了这条路和其他几个地方,仍然一无所获。也许我忽略了某种配置问题,但我无法想象它会是什么。也许这里有人可以 MainPage.xaml.cs using S

简而言之,这是一个Windows应用商店应用程序,在Visual Studio 2013中使用F5运行时无法发出多个HTTP请求。目标平台是Windows 8.1

每次单击按钮时,都会从公共服务器请求时间信息并显示响应。然而,正如Fiddler所示,尽管相关的click事件处理程序被反复运行,但实际的HTTP请求仅在第一次单击时发出

我已经走过了这条路和其他几个地方,仍然一无所获。也许我忽略了某种配置问题,但我无法想象它会是什么。也许这里有人可以

MainPage.xaml.cs

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Web.Http;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238

namespace TestWindowsStore
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        private readonly Uri timeInfoHost = new Uri("http://jsontime-sharpnet.rhcloud.com/");
        private readonly HttpClient httpClient = new HttpClient();

        public MainPage()
        {
            this.InitializeComponent();

            var headers = httpClient.DefaultRequestHeaders;
            headers.UserAgent.ParseAdd("ie");
            headers.UserAgent.ParseAdd("Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            TimeInfo ti = await PerformTimeRequest();
            this.TimeText.Text = ti.datetime;
        }

        private async Task<TimeInfo> PerformTimeRequest()
        {
            string json = await httpClient.GetStringAsync(timeInfoHost);
            return Deserialize<TimeInfo>(json);
        }

        public T Deserialize<T>(string json)
        {
            var bytes = Encoding.Unicode.GetBytes(json);
            using (MemoryStream ms = new MemoryStream(bytes))
            {
                var jser = new DataContractJsonSerializer(typeof(T));
                return (T) jser.ReadObject(ms);
            }
        }
    }

    [DataContract]
    public class TimeInfo
    {
        [DataMember]
        public string tz;
        [DataMember]
        public string hour;
        [DataMember]
        public string datetime;
        [DataMember]
        public string second;
        [DataMember]
        public string error;
        [DataMember]
        public string minute;
    }
}
使用系统;
使用System.IO;
使用System.Runtime.Serialization;
使用System.Runtime.Serialization.Json;
使用系统文本;
使用System.Threading.Tasks;
使用Windows.UI.Xaml;
使用Windows.UI.Xaml.Controls;
使用Windows.Web.Http;
//空白页项模板被记录在http://go.microsoft.com/fwlink/?LinkId=234238
命名空间TestWindowsStore
{
/// 
///可以单独使用或在框架内导航到的空页。
/// 
公共密封部分类主页面:第页
{
私有只读Uri timeInfoHost=新Uri(“http://jsontime-sharpnet.rhcloud.com/");
私有只读HttpClient HttpClient=新HttpClient();
公共主页()
{
this.InitializeComponent();
var headers=httpClient.DefaultRequestHeaders;
headers.UserAgent.ParseAdd(“ie”);
headers.UserAgent.ParseAdd(“Mozilla/5.0(兼容;MSIE10.0;WindowsNT6.2;WOW64;Trident/6.0)”;
}
专用异步无效按钮\u单击(对象发送方,路由目标)
{
TimeInfo ti=wait PerformTimeRequest();
this.TimeText.Text=ti.datetime;
}
专用异步任务PerformTimeRequest()
{
string json=await httpClient.GetStringAsync(timeInfoHost);
返回反序列化(json);
}
公共T反序列化(字符串json)
{
var bytes=Encoding.Unicode.GetBytes(json);
使用(MemoryStream ms=新的MemoryStream(字节))
{
var jser=新的数据契约jsonserializer(typeof(T));
return(T)jser.ReadObject(ms);
}
}
}
[数据合同]
公共类时间信息
{
[数据成员]
公共字符串tz;
[数据成员]
公共弦乐小时;
[数据成员]
公共字符串日期时间;
[数据成员]
公共字符串第二;
[数据成员]
公共字符串错误;
[数据成员]
公共字符串分钟;
}
}
MainPage.xaml

<Page
x:Class="TestWindowsStore.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestWindowsStore"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <TextBox Name="TimeText" HorizontalAlignment="Left" Margin="491,242,0,0" TextWrapping="Wrap" VerticalAlignment="Top" IsReadOnly="True" Width="144"/>
    <Button Content="Get Time Async" HorizontalAlignment="Left" Margin="648,239,0,0" VerticalAlignment="Top" Click="Button_Click"/>

</Grid>
</Page>


为什么没有任何后续请求?如何修复它?

此处仅执行一次请求的原因是,默认情况下,
HttpClient
使用缓存根据收到的
缓存控制
头存储响应(类似于)。有两种方法可以解决这个问题

最简单的解决方案是使用
HttpBaseProtocolFilter.CacheControl.ReadBehavior
属性来处理要跳过缓存的情况:

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);

但是,我认为更干净的解决方案是修改服务器,使其包含适当的标头,它指示浏览器不缓存响应,即:

Cache-Control: no-cache
例如:

第二种解决方案有两个优点:

  • 不再使用的内容不会存储在客户端计算机中
  • 其他请求可以从缓存中受益(当使用相同的
    HttpClient
    实例时)

此处仅执行一次请求的原因是,默认情况下,
HttpClient
使用缓存根据收到的
缓存控制
头存储响应(类似于)。有两种方法可以解决这个问题

最简单的解决方案是使用
HttpBaseProtocolFilter.CacheControl.ReadBehavior
属性来处理要跳过缓存的情况:

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);

但是,我认为更干净的解决方案是修改服务器,使其包含适当的标头,它指示浏览器不缓存响应,即:

Cache-Control: no-cache
例如:

第二种解决方案有两个优点:

  • 不再使用的内容不会存储在客户端计算机中
  • 其他请求可以从缓存中受益(当使用相同的
    HttpClient
    实例时)

您很可能正在读取给定URL处的文件缓存副本…@ChrisK-可能是,但副本缓存在哪里?如何清空或禁用该缓存?我认为HttpClient将使用“全局”IE缓存。是否可以尝试在末尾附加一个随机GUID作为变量,以防止缓存?因此,url看起来类似于“”,如果服务器正确设置了缓存头,您就不必担心这一点。为什么要在网络中检索两次相同的表示?当最长期限到期时,下一个请求应自动通过网络。如果必须忽略服务器缓存指令,则发送“无缓存”。@Darreller-您不明白。这个问题的目的是找出为什么没有执行明确命令的请求。由于中没有提到缓存,所以我假设没有缓存。如果我知道
HttpClient
根据HTTP头缓存表示,那么这个问题就不存在了。您很可能正在给定URL处读取文件的缓存副本…@ChrisK-可能是,但缓存副本在哪里?如何清空或禁用该缓存?我认为HttpClient将使用“全局”IE缓存。是否可以尝试在末尾附加一个随机GUID作为变量,以防止缓存?因此,如果服务器正确设置了缓存头,url看起来像“”,您应该