Display Local Weather Forecasts with the NOAA's Web ServiceBy Scott Mitchell
In December 2004 the National Oceanic and Atmosphere Administration (NOAA) unveiled a Web service for accessing weather forecasts for locations within the United States. The Web service provides two methods:
NDFDgen(latitude, longitude, detailLevel, startTime, endTime, weatherParametersToReturn)- returns a range of weather information for a particular latitude and longitude between a start and end time. The weatherParametersToReturn input parameter dictates what weather information should be returned, such as: maximum temperature, minimum temperature, three hour temperature, snowfall amount, wind speed, and so on.
NDFDgenByDay(latitude, longitude, hourlyFormat, startDate, numberOfDays)- returns 12-hour or 24-hour weather information for a particular latitude/longitude starting from a certain date and extending a specified number of dates into the future.
When reading up on this new Web service, I stumbled across Mikhail Arkhipov's blog entry titled Weather Forecast ASP.NET User Control, which provides a User Control written in C# for displaying the seven-day forecast for a particular latitude and longitude. While Mikhail's User Control definitely fit the bill for a simple forecast display in a C# Web application, I was tempted to provide similar functionality in a custom, compiled server control, which would allow the weather forecasts to be displayed in VB.NET Web applications as well. Additionally, I wanted to add some additional customization not found in Mikhail's solution.
The remainder of this article examines my custom control, MultiDayForecast (see screenshot below). We'll look at creating the proxy class for calling the Web service, techniques used to enhance the performance, how to customize the appearance of the MultiDayForecast control, and see how to use MultiDayForecast in an ASP.NET page. (If you are just interested in seeing how to use the MultiDayForecast control on an ASP.NET page and do not care to learn how the control works underneath the covers, feel free to skip to the Using MultiDayForecast in an ASP.NET Page section.) Read on to learn more!
Utilizing the NOAA's Web Service
In order to display a forecast to an end user, we first need to access the weather information for a particular latitude and longitude through the NOAA's Web service. As discussed in An Extensive Examination of Web Services, calling a Web service from a client application is a trivial task thanks to the concept of proxy classes. A proxy class is class that is auto-generated from the Web service's Web Service Description Language (WSDL) contract, encapsulating the complexity in calling the Web service. The proxy class provides the same set of methods as the Web service and these methods, when called by the client, do all of the hard work involved in invoking a Web service (formatting the call into a SOAP request, making an HTTP request to the Web service, retrieving and parsing the HTTP response, and returning a value to the client application). (This article does not intend to discuss Web services in-depth; be sure to consult An Extensive Examination of Web Services for more information on the fundamentals of Web services.)
To create a proxy class, simply add a Web Reference (from Visual Studio .NET, right-click on References
and select Add Web Reference). In the Add Web Reference dialog box, enter the URL to the NOAA's Web service's
WSDL document - http://weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl.
The generated proxy class will have two methods:
(The MultiDayForecast control uses the latter method to get forecast information for a specified number
Unfortunately the Web service's methods both return an XML string as their result. This means that upon calling
these methods, we'll need to programmatically parse the XML data to pick out the particular bits of interest.
To accomplish this I use an
XmlDocument object with XPath expressions to snip out the pieces of interest.
(For more on XPath be sure to read this FAQ
as well as the W3Schools XPath Tutorial.)
The data extracted from the XML document is stored in the
DayWeatherData class I created, which
has properties for each of the bits from the weather forecast that can be shown in the MultiDayForecast control:
DateTime- the date of the weather forecast
LowTempF- the forecasted low temperature for the day, in Fahrenheit
LowTempC- the forecasted low temperature for the day, in Celsius (a read-only property; computed from the
HighTempF- the forecasted high temperature for the day, in Fahrenheit
HighTempC- the forecasted high temperature for the day, in Celsius (a read-only property; computed from the
CloudIconURL- the icon to use to display the day's conditions. (The NOAA's Web service provides a standard set of 55x58 sized JPEG images for differing weather conditions. The XML data returned provides URLs to these images for each day.)
Enhancing the Performance of MultiDayForecast
In my initial design, when MultiDayForecast exists on an ASP.NET page, every time the page was loaded - be it on the first visit to the page for a user or on a postback - the MultiDayForecast control made a request out to the NOAA's Web service. In my tests, the NOAA's Web service was usually pretty responsive, but sometimes it could take several seconds to receive a response from the Web service, which therefore had the effect of having the page hang.
Since 24-hour weather forecasts don't change that often and since the data can be shared among multiple users, the weather data is a prime candidate for caching. I decided to cache the XML string returned by the call to the Web service for a period of two hours. Therefore, if the cache does not contain the XML results from the Web service, the Web service will be invoked and the response added to the cache. Otherwise, if the response is found in the cache, the Web service call can be bypassed. This greatly improves performance and amortizes the cost of the Web service call across the users accessing the site.
Shown below is the code that caches the XML results. This code is a modified version of the code we examined in the last code block.
Notice that the XML data is cached using the
cacheKey variable, which is a combination of
the latitude, longitude, start date, and number of days to forecast. This combination of variables was used
in constructing the
cacheKey so that different instances of the MultiDayForecast control on
the site using different latitudes/longitudes, start date, or days to forecast can each have their own
cached copy of the results.
Using MultiDayForecast in an ASP.NET Page
To use the MultiDayForecast control in an ASP.NET page you'll first need to download the control's code and/or compiled assembly, which are available at the end of this article. If your Web site is running ASP.NET 1.1 (that is, if you are using Visual Studio .NET 2003), then you can simply save the compiled assembly (
WeatherInfo.dll) to your computer and add it to the Visual Studio .NET Toolbox. (To add an item to the Toolbox, right-click on the Toolbox and choose Add/Remove Items (in VS.NET 2002 it will be Customize Toolbox). Then Browse to the assembly and click OK. This should add an item to your Toolbox named MultiDayForecast.) If you are running ASP.NET 1.0 you will need to create a new project in Visual Studio 2002 and manually add the
.csfiles from the download and build the project. This will result in a compiled assembly,
WeatherInfo.dll, which you can then add to the Toolbox using the steps discussed earlier.
Once you have the MultiDayForecast in the Toolbox, you should be able to simply drag and drop it onto an ASP.NET page's Design view. The screenshot to the right shows the MultiDayForecast control after it has been added to an ASP.NET page.
The following MultiDayForecast properties are the ones that are responsible what data to request from the NOAA's Web service:
Latitude- the latitude of the location. Must be within the NOAA's database, which is limited to the United States. Defaults to 32.7452, the latitude of San Diego, CA.
Longitude- the longitude of the location. Must be within the NOAA's database, which is limited to the United States. Defaults to -117.1979, the longitude of San Diego, CA.
DaysToForecast- the number of days to forecast. Defaults to 5.
StartDate- the starting date of the forecast; defaults to the current date. This property cannot be set through the Properties pane and likely shouldn't ever be specified (either declaratively or programmatically), unless you want the forecast for a particular date instead of the current date.)
Longitudeproperty values to get the forecast for your area. You can find latitude and longitude coordinates for various cities by searching on Google.
Customizing the Appearance of MultiDayForecast
The MultiDayForecast control has a number of properties that can be used to customize the appearance of the forecast in the end user's browser:
ForecastLayout- indicates if the weather forecast is laid out horizontally or vertically.
HeaderText- the text to display atop the forecast; defaults to "Weather Forecast". (The text is only displayed if
ShowHeaderis true (the default).)
LowTempStyle- style information dictating how the each day's forecast is displayed, how the date in the forecast is displayed, how the weather conditions image is displayed, how the high temperature is displayed, and how the low temperature is displayed.
DateFormatString- the format string to use when displaying the forecast's date. Defaults to "D", which is a long date (i.e., Monthname, Day, Year).
In this article we examined the MultiDayForecast control, a compiled, custom server control that utilizes the NOAA's Web service to display a weather forecast for a particular location within the United States. This control can be used in an ASP.NET Web page by simply dragging and dropping from the Toolbox onto the designer.
The MultiDayForecast control is completely functional at this point but could use a few improvements, which I intend to do in a later article. My tentative list of improvements include:
- The ability to specify a timeout so if the NOAA's Web service takes too long to respond, the control will sever the request so as not to hang the requested ASP.NET page.
- Finer tuned exception handling. Right now, if an exception occurs when requesting the Web service's data, a simple, "We're having problems"-type message is displayed. Ideally there would be a way to provide a page developer with richer information about the exception, but not dump a technical error message to the end user.