WeatherInformation: WP8
authorgu.martinm@gmail.com <gu.martinm@gmail.com>
Sun, 3 Aug 2014 22:25:09 +0000 (00:25 +0200)
committergu.martinm@gmail.com <gu.martinm@gmail.com>
Sun, 3 Aug 2014 22:25:09 +0000 (00:25 +0200)
HTTP client improvements
Many others (no time...)

WindowsPhone/WeatherInformation/WeatherInformation/App.xaml.cs
WindowsPhone/WeatherInformation/WeatherInformation/MainPage.xaml
WindowsPhone/WeatherInformation/WeatherInformation/Model/Services/CustomHTTPClient.cs
WindowsPhone/WeatherInformation/WeatherInformation/SampleData/SelectedDateViewModelSampleData.xaml
WindowsPhone/WeatherInformation/WeatherInformation/SelectedDatePage.xaml
WindowsPhone/WeatherInformation/WeatherInformation/SelectedDatePage.xaml.cs
WindowsPhone/WeatherInformation/WeatherInformation/ViewModels/MainViewModel.cs
WindowsPhone/WeatherInformation/WeatherInformation/ViewModels/SelectedDateViewModel.cs

index 31d00b4..338023f 100644 (file)
@@ -298,6 +298,9 @@ namespace WeatherInformation
 
         // Código para ejecutar cuando la aplicación se desactiva (se envía a segundo plano)
         // Este código no se ejecutará cuando la aplicación se cierre
+        // TODO: no siempre pasa por aqui cuando se lanza una nueva ventana de la misma aplicación.
+        //       Y POR ESO HAY PROBLEMAS CON GetDataAsync PORQUE ESTO NO TIENE NADA DE NADA Y DEVUELVE NULL
+        //       Y SIEMPRE HACE UNA PETICIÓN AL SERVIDOR :(
         private void Application_Deactivated(object sender, DeactivatedEventArgs e)
         {
             // If there is data in the application member variable...
index 084a4fd..f15066d 100644 (file)
                                 </StackPanel>
                             </StackPanel>
                         </StackPanel>
-                        <StackPanel Grid.Column="0" Grid.Row="1" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
+                        <StackPanel Grid.Column="0" Grid.Row="1" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,28,0,0">
                             <TextBlock Text="{Binding CurrentConditions}" TextWrapping="Wrap" Style="{StaticResource PhoneTextLargeStyle}" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" Margin="2,0"/>
                         </StackPanel>
-                        <Grid Grid.Column="0" Grid.Row="2" HorizontalAlignment="Center">
+                        <Grid Grid.Column="0" Grid.Row="2" HorizontalAlignment="Center" Margin="0,28,0,0">
                             <Grid.ColumnDefinitions>
                                 <ColumnDefinition Width="Auto" />
                                 <ColumnDefinition Width="Auto" />
                             </StackPanel>
                         </Grid>
                         <StackPanel Grid.Column="0" Grid.Row="3" VerticalAlignment="Center" HorizontalAlignment="Center">
-                            <StackPanel Orientation="Horizontal">
+                            <StackPanel Orientation="Horizontal" Margin="0,28,0,0">
                                 <TextBlock Text="{Binding CurrentPressureText}" TextWrapping="Wrap" Style="{StaticResource PhoneTextTitle3Style}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="2,0"/>
                                 <TextBlock Text="{Binding CurrentPressure}" TextWrapping="Wrap" Style="{StaticResource PhoneTextSubtleStyle}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10,0,2,0"/>
                                 <TextBlock Text="{Binding CurrentPressureUnits}" TextWrapping="Wrap" Style="{StaticResource PhoneTextTitle3Style}" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" Margin="2,0"/>
index c9c2bef..aa98917 100644 (file)
@@ -1,6 +1,6 @@
 using System;
-using System.Collections.Generic;
-using System.Linq;
+using System.IO;
+using System.Net;
 using System.Net.Http;
 using System.Net.Http.Headers;
 using System.Text;
@@ -10,23 +10,73 @@ namespace WeatherInformation.Model.Services
 {
     class CustomHTTPClient
     {
-        async public Task<string> GetWeatherDataAsync(string url)
+        async public Task<string> GetWeatherDataAsync(string uri)
         {
-            
-            using (HttpClient client = new HttpClient { Timeout = TimeSpan.FromSeconds(30) })
+            if (string.IsNullOrEmpty(uri))
             {
-                // TODO: I wish my string to be converted to UTF-8. WTH is doing HttpClient? Dunno :(
-                // How do I control the encoding used by HttpClient?
+                throw new ArgumentException("Missing argument", "uri");
+            }
 
-                // Disable WindowsPhone cache
+            // TODO: it would be nice to use the same HttpClient for the the 2 requests instead of creating
+            //       a new one for each connection. :( Not easy with using statement and async :(
+            using(HttpClientHandler handler = new HttpClientHandler
+            {
+                // TODO: check if this really works when receiving compressed data.
+                AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
+            })
+            using (HttpClient client = new HttpClient(handler) { Timeout = TimeSpan.FromSeconds(30) })
+            {
                 HttpRequestHeaders headers = client.DefaultRequestHeaders;
-                headers.IfModifiedSince = DateTime.UtcNow;
 
-                // TODO: THIS IS FUCKED UP. IT IS WORKING RANDOMLY... THE MOST OF THE TIMES IT STOPS HERE FOREVER...
-                string jsonData = await client.GetStringAsync(url);
+                headers.UserAgent.Clear();
+                headers.UserAgent.Add(new ProductInfoHeaderValue(new ProductHeaderValue("WeatherInformation", "WP8")));
+
+                headers.AcceptCharset.Clear();
+                headers.AcceptCharset.Add(new StringWithQualityHeaderValue("utf-8"));
+
+                headers.Accept.Clear();
+                headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
 
-                return jsonData;
+                headers.AcceptEncoding.Clear();
+                headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
+                headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate"));
+
+                // Bypassing Windows cache
+                DateTime currentDate = DateTime.UtcNow;
+                string uriWindowsCacheSucks = String.Concat(uri, currentDate);
+
+                // TODO: HttpCompletionOption, without it, by default, I am buffering the received data.
+                //       in this case it is not a problem but when receiving loads of bytes I do not
+                //       think it is a great idea to buffer all of them... :(
+                using (HttpResponseMessage response = await client.GetAsync(uriWindowsCacheSucks))
+                {
+                    response.EnsureSuccessStatusCode();
+
+                    using (HttpContent contentRESULT = response.Content)
+                    {
+                        return await this.ReadResponseAsync(contentRESULT);
+                    }
+                }
+            }
+        }
+
+        async private Task<string> ReadResponseAsync(HttpContent content)
+        {
+            Encoding encoding;
+            if (content.Headers != null && content.Headers.ContentType != null && content.Headers.ContentType.CharSet != null)
+            {
+                encoding = Encoding.GetEncoding(content.Headers.ContentType.CharSet);
+            }
+            else
+            {
+                encoding = Encoding.UTF8;
+            }
+
+            using (Stream stream = await content.ReadAsStreamAsync())
+            using (StreamReader streamReader = new StreamReader(stream, encoding))
+            {
+                return await streamReader.ReadToEndAsync();
             }
-        } 
+        }
     }  
 }
index 30098de..bbc7f3e 100644 (file)
@@ -1,5 +1,6 @@
 <ViewModels:SelectedDateViewModel
     xmlns:ViewModels="clr-namespace:WeatherInformation.ViewModels"
+    TitleTextCityCountry="City,country"
     SelectedDate="July 27"
     SelectedDateRainText="RAIN"
     SelectedDateMaxTempUnits="ºC"
index 86271fc..6ece602 100644 (file)
@@ -27,7 +27,7 @@
 <!--LayoutRoot es la cuadrícula raíz donde se coloca todo el contenido de la página-->
        <Grid x:Name="LayoutRoot" Background="Transparent">
         <!--Control Pivot-->
-               <phone:Pivot x:Name="TitleTextCityCountry" Title="{Binding LocalizedResources.MainPageTitle, Mode=OneWay, Source={StaticResource LocalizedStrings}}">
+               <phone:Pivot x:Name="TitleTextCityCountry" Title="{Binding TitleTextCityCountry}">
                        <!--Elemento Pivot uno-->
                        <phone:PivotItem Header="{Binding SelectedDate}">
                 <ScrollViewer HorizontalScrollBarVisibility="Auto">
index 8fd70ae..fc2cfca 100644 (file)
@@ -62,13 +62,6 @@ namespace WeatherInformation
                 }
 
                 _selectedDateViewModel.LoadData(weatherData);
-
-                // TODO: Should I try to move this code to MainViewModel. It seems so but how?
-                // TODO: What if the address is not available? I should show something like "Address not found" by default...
-                string country = (string)IsolatedStorageSettings.ApplicationSettings["Country"];
-                string city = (string)IsolatedStorageSettings.ApplicationSettings["City"];
-                string cityCountry = String.Format(CultureInfo.InvariantCulture, "{0}, {1}", city, country);
-                this.TitleTextCityCountry.Title = cityCountry;
             }
         }
     }
index 470d397..6393509 100644 (file)
@@ -111,14 +111,6 @@ namespace WeatherInformation.ViewModels
             }
             double tempUnits = isFahrenheit ? 0 : 273.15;
             string symbol = isFahrenheit ? AppResources.TemperatureUnitsFahrenheitSymbol : AppResources.TemperatureUnitsCentigradeSymbol;
-
-
-            // TODO: What if address is not available? I should show something like "Address not found" by default...
-            string country = (string)IsolatedStorageSettings.ApplicationSettings["Country"];
-            string city = (string)IsolatedStorageSettings.ApplicationSettings["City"];
-            string cityCountry = String.Format(CultureInfo.InvariantCulture, "{0}, {1}", city, country);
-            this.TitleTextCityCountry = cityCountry;
-
             DateTime unixTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
 
             var remoteForecastWeatherData = weatherData.RemoteForecast;
@@ -293,6 +285,13 @@ namespace WeatherInformation.ViewModels
                 this.CurrentSunSet = sunSetTime.ToString("MM/dd/yy H:mm:ss", CultureInfo.InvariantCulture);
                 NotifyPropertyChanged("CurrentSunSet");
                 NotifyPropertyChanged("CurrentSunSetText");
+
+                // TODO: What if address is not available? I should show something like "Address not found" by default...
+                string country = StoredLocation.Country;
+                string city = StoredLocation.City;
+                string cityCountry = String.Format(CultureInfo.InvariantCulture, "{0}, {1}", city, country);
+                this.TitleTextCityCountry = cityCountry;
+                NotifyPropertyChanged("TitleTextCityCountry");
             }
 
         }
index 1fa3430..93a4bc9 100644 (file)
@@ -7,6 +7,7 @@ using System.Runtime.Serialization;
 using System.Text;
 using System.Threading.Tasks;
 using WeatherInformation.Model;
+using WeatherInformation.Model.Services;
 using WeatherInformation.Resources;
 
 namespace WeatherInformation.ViewModels
@@ -17,6 +18,8 @@ namespace WeatherInformation.ViewModels
         [DataMember]
         public Int32 SelectedDateIndex { get; set; }
 
+        public String TitleTextCityCountry { get; private set; }
+
         public String SelectedDate { get; private set; }
         public String SelectedDateMaxTemp { get; private set; }
         public String SelectedDateMaxTempUnits { get; private set; }
@@ -202,6 +205,13 @@ namespace WeatherInformation.ViewModels
             NotifyPropertyChanged("SelectedDateNightTemp");
             this.SelectedDateNightTempUnits = selectedDateTempUnits;
             NotifyPropertyChanged("SelectedDateNightTempUnits");
+
+            // TODO: What if address is not available? I should show something like "Address not found" by default...
+            string country = StoredLocation.Country;
+            string city = StoredLocation.City;
+            string cityCountry = String.Format(CultureInfo.InvariantCulture, "{0}, {1}", city, country);
+            this.TitleTextCityCountry = cityCountry;
+            NotifyPropertyChanged("TitleTextCityCountry");
         }
 
         public event PropertyChangedEventHandler PropertyChanged;