Tag Archives: Web Services

NOAA Weather Service and .NET

I have been fighting with the national weather web service, provided by the National Oceanic and Atmospheric Administration, today.  Like a lot of developers, who like to make their web sites fancy with the current weather forecast, I have been developing a component for the web site I am working on.

NOAA seems to be the norm for providing weather data in XML via the SOAP web service protocol.  Up until a couple of weeks ago, the C# code that I had to connect to the NOAA web service and pull weather data, was working  nicely….then it stopped – bah.  The proxy code (generated from the service WSDL by .NET) kept throwing an HTTP protocol violation exception:

Unhandled Exception: System.Net.WebException: Error getting response
stream (Rea dDone2): ReceiveFailure ---> System.Exception:
at System.Net.WebConnection.HandleError ()
at System.Net.WebConnection.ReadDone ()
at System.MulticastDelegate.invoke_void_IAsyncResult ()
at System.Net.Sockets.Socket+SocketAsyncResult.Complete ()
at System.Net.Sockets.Socket+Worker.Receive ()
at System.MulticastDelegate.invoke_void ()
in <0x000ad> System.Net.WebConnection:HandleError (WebExceptionStatus
st, System.Exception e, System.String where)--- End of inner exception
stack trace ---
in <0x00158> System.Net.HttpWebRequest:EndGetResponse (IAsyncResult
asyncResult)in <0x00047> System.Net.HttpWebRequest:GetResponse ()
in <0x0004d>
System.Web.Services.Protocols.WebClientProtocol:GetWebResponse (Sys
tem.Net.WebRequest request)

It seems that NOAA changed something involving their service protocol, because the response to a SOAP request is now being returned in separate chunked HTTP responses, which causes the .NET SOAP client to puke.

After some digging on the Internet (lots of digging in fact), I came across a post on a Mono newsgroup, which gave me a work around to the problem.  The trick is to change the web request in the SOAP proxy to use HTTP version 1.0 instead of 1.1.  Since HTTP 1.0 does not support chunked response, the NOAA server sends the response data as one block, which keeps the .NET SOAP client happy. 

Below is the code for my web service proxy, drop it into your project (assuming you use C#) and instantiate the WeatherProxy class from your code.  You’ll not need to add a web reference to your project because this proxy class is attributed with the correct SOAP envelope information.

///
/// Soap Format Type.
///
[SoapTypeAttribute(“formatType”, “http://weather.gov/forecasts/xml/DWMLgen/schema/ndfdXML.xsd”)]
public enum formatType
{
///
/// 24 Hour
///
[SoapEnumAttribute(“24 hourly”)]
Item24hourly,

///
/// 12 Hour
///
[SoapEnumAttribute(“12 hourly”)]
Item12hourly,
}

///
/// Proxy class for weather service.
///
///
/// Uses the NOAA web service, this proxy derived from an example found on the .NET. The proxy that
/// VS2005 generates causes a protocol error/HTTP 502 Bad Gateway.
///
[DesignerCategoryAttribute(“code”)]
[WebServiceBindingAttribute(Name = “ndfdXMLBinding”, Namespace = “http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl”)]
public class WeatherProxy : System.Web.Services.Protocols.SoapHttpClientProtocol
{
#region Construction

///
/// Constructor.
///
public WeatherProxy()
{
this.Url = “http://www.weather.gov/forecasts/xml/SOAP_server/ndfdXMLserver.php”;
}

#endregion Construction

#region Methods

///
/// Get the weather data by day (synchronously).
///
/// Latitude coord.
/// Longitude coord.
/// Start Date.
/// Number of days.
/// Time format.
/// Soap XML
[SoapRpcMethodAttribute(“http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl#NDFDgenByDay”, RequestNamespace = “http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl”, ResponseNamespace = “http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl”)]
[return: SoapElementAttribute(“dwmlByDayOut”)]
public string NDFDgenByDay(
Decimal latitude, Decimal longitude,
[SoapElementAttribute(DataType = “date”)] DateTime startDate,
int numDays, formatType format)
{
object[] results = this.Invoke(“NDFDgenByDay”, new object[] {
latitude,
longitude,
startDate,
numDays,
format});
return ((string)(results[0]));
}

/// Creates a for the specified uri.
/// The .
/// The to use when creating the .
/// The uri parameter is null.
protected override WebRequest GetWebRequest(Uri uri)
{
HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(uri);
request.ProtocolVersion = HttpVersion.Version10;
return request;
}

#endregion Methods

}