/// <summary> /// Get a forecast for the given latitude and longitude /// </summary> public void GetForecast(string latitude, string longitude) { // form the URI UriBuilder fullUri = new UriBuilder("http://forecast.weather.gov/MapClick.php"); fullUri.Query = "lat=" + latitude + "&lon=" + longitude + "&FcstType=dwml"; // initialize a new WebRequest HttpWebRequest forecastRequest = (HttpWebRequest)WebRequest.Create(fullUri.Uri); // set up the state object for the async request ForecastUpdateState forecastState = new ForecastUpdateState(); forecastState.AsyncRequest = forecastRequest; // start the asynchronous request forecastRequest.BeginGetResponse(new AsyncCallback(HandleForecastResponse), forecastState); }
/// <summary> /// Handle the information returned from the async request /// </summary> /// <param name="asyncResult"></param> private void HandleForecastResponse(IAsyncResult asyncResult) { // get the state information ForecastUpdateState forecastState = (ForecastUpdateState)asyncResult.AsyncState; HttpWebRequest forecastRequest = (HttpWebRequest)forecastState.AsyncRequest; // end the async request forecastState.AsyncResponse = (HttpWebResponse)forecastRequest.EndGetResponse(asyncResult); Stream streamResult; string newCredit = ""; string newCityName = ""; int newHeight = 0; // create a temp collection for the new forecast information for each // time period ObservableCollection <ForecastPeriod> newForecastList = new ObservableCollection <ForecastPeriod>(); try { // get the stream containing the response from the async call streamResult = forecastState.AsyncResponse.GetResponseStream(); // load the XML XElement xmlWeather = XElement.Load(streamResult); // start parsing the XML. You can see what the XML looks like by // browsing to: // http://forecast.weather.gov/MapClick.php?lat=44.52160&lon=-87.98980&FcstType=dwml // find the source element and retrieve the credit information XElement xmlCurrent = xmlWeather.Descendants("source").First(); newCredit = (string)(xmlCurrent.Element("credit")); // find the source element and retrieve the city and elevation information xmlCurrent = xmlWeather.Descendants("location").First(); newCityName = (string)(xmlCurrent.Element("city")); newHeight = (int)(xmlCurrent.Element("height")); // find the first time layout element xmlCurrent = xmlWeather.Descendants("time-layout").First(); int timeIndex = 1; // search through the time layout elements until you find a node // contains at least 12 time periods of information. Other nodes can be ignored while (xmlCurrent.Elements("start-valid-time").Count() < 12) { xmlCurrent = xmlWeather.Descendants("time-layout").ElementAt(timeIndex); timeIndex++; } ForecastPeriod newPeriod; // For each time period element, create a new forecast object and store // the time period name. // Time periods vary depending on the time of day the data is fetched. // You may get "Today", "Tonight", "Monday", "Monday Night", etc // or you may get "Tonight", "Monday", "Monday Night", etc // or you may get "This Afternoon", "Tonight", "Monday", "Monday Night", etc foreach (XElement curElement in xmlCurrent.Elements("start-valid-time")) { try { newPeriod = new ForecastPeriod(); newPeriod.TimeName = (string)(curElement.Attribute("period-name")); newForecastList.Add(newPeriod); } catch (FormatException) { } } // now read in the weather data for each time period GetMinMaxTemperatures(xmlWeather, newForecastList); GetChancePrecipitation(xmlWeather, newForecastList); GetCurrentConditions(xmlWeather, newForecastList); GetWeatherIcon(xmlWeather, newForecastList); GetTextForecast(xmlWeather, newForecastList); // copy the data over Deployment.Current.Dispatcher.BeginInvoke(() => { // copy forecast object over Credit = newCredit; Height = newHeight; CityName = newCityName; ForecastList.Clear(); // copy the list of forecast time periods over foreach (ForecastPeriod forecastPeriod in newForecastList) { ForecastList.Add(forecastPeriod); } }); } catch (FormatException) { // there was some kind of error processing the response from the web // additional error handling would normally be added here return; } }