Question

In brief, here is a Windows Store application that fails to make more than one HTTP request when run with F5 in Visual Studio 2013. The target platform is Windows 8.1.

Every time a button is clicked, it is supposed request time information from a public server and display the response. However, as Fiddler shows, an actual HTTP request is made only for the first click, despite the relevant click event handler being run over and over again.

I have gone through the API docs and several other places, still nothing. Perhaps I am overlooking some kind of a configuration issue but I cannot imagine what it could be. Maybe someone here can?

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

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>

Why aren't any subsequent requests made? How can I fix it?

Was it helpful?

Solution

The reason why a request is performed only once here is because by default, HttpClient uses a cache to store responses according to received Cache-Control headers (similar to HTTPClient Caching in .Net). There are two ways to work around it.

The easiest solution is to use HttpBaseProtocolFilter.CacheControl.ReadBehavior property to handle cases when you want to skip the cache:

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

However, a solution I consider cleaner is to modify your server so it includes the appropriate headers that tell browsers do not cache the response, i.e.:

Cache-Control: no-cache

E.g.:

HTTP/1.1 200 OK
Content-Length: 31
Content-Type: text/plain; charset=UTF-8
Cache-Control: no-cache

... 

The second solution has two advantages:

  • A content you will not use again is not stored in the client machine.
  • Other requests can benefit from the cache (when using the same instance of HttpClient).
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top