UPDATED: there's a new implementation post here that uses MVC's built-in AJAX functionality.
a lot of places sell data, and often quite pricy too.. there are however a few that actually gives it away, i like that.
yr.no (the Norwegian Meteorological Institute and the NRK) exposes their weather data in xml format, both in norwegian as well as in english. I figured it was about time i tried it out since i really wanted to have some weather data on the discgolf site.
first, the basics:
the code i’m demonstrating is written in ASP.NET MVC, but it’s not anywhere near MVC-specific so you can easily take it all and run in your own solution.
for this example we’re gonna be using the following url:
http://www.yr.no/place/Sweden/Stockholm/J%c3%a4rva/forecast.xml
at yr.no it’s pretty easy to grab the url to the city of your choice (as long as they hold data for that city): just find it on their site and add forecast.xml in the end of the url.
so, after creating a partial view and setting some initial code up we get to consume the data from yr.no and output it to our site:
code:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<DiscMaster.Web.Models.Course>" %> <%@ Import Namespace="System.Xml" %> <% System.Xml.XmlDocument doc = new XmlDocument(); if (Cache[Server.UrlPathEncode(Model.CourseDetail.yr_weather)]!=null) { doc = (XmlDocument)Cache[Server.UrlPathEncode(Model.CourseDetail.yr_weather)]; } else { try { System.Xml.XmlTextReader reader = new XmlTextReader(Server.UrlPathEncode(Model.CourseDetail.yr_weather)); doc.Load(reader); Cache.Add(Server.UrlPathEncode(Model.CourseDetail.yr_weather), doc, null, DateTime.Now.AddMinutes(60), Cache.NoSlidingExpiration, CacheItemPriority.Default, null); } catch (Exception ex) { throw; } } System.Xml.XmlNodeList nodelist = doc.SelectNodes("/weatherdata/forecast/tabular/time"); for (int i = 0; i < 4; i++) { %> <p> <strong><%= DateTime.Parse(nodelist[i].Attributes["from"].Value).ToString("yyyy-mm-dd HH:MM") %> - <%= DateTime.Parse(nodelist[i].Attributes["to"].Value).ToString("HH:MM")%></strong> <br /> <img src='<%= String.Format("/Image.ashx?src=/Content/Media/Icons/Weather/{0}.png&width=32", nodelist[i]["symbol"].Attributes["number"].Value.PadLeft(2,'0')) %>' /> conditions: <%= nodelist[i]["symbol"].Attributes["name"].Value%> <br /> temperature: <%= nodelist[i]["temperature"].Attributes["value"].Value%><sup>o</sup>C <br /> precipitation: <%= nodelist[i]["precipitation"].Attributes["value"].Value%> <br /> wind: <%= nodelist[i]["windSpeed"].Attributes["name"].Value%> - <%= nodelist[i]["windSpeed"].Attributes["mps"].Value%> mps <%= nodelist[i]["windDirection"].Attributes["code"].Value%> </p> <% } %> <small> Weather forecast from <a href="http://www.yr.no" target="_blank">yr.no</a> delivered by the Norwegian Meteorological Institute and the NRK </small>
view:
nothing major really in that code.. the green-highlighted text in the example code is where the actual url to the xml data is entered.
a few minutes more and the code is more optimized to handle errors, linq and in the end i even had the time to throw in a little jQuery i found over at DynamicDrive called Featured Content Glider that i thought would do nicely for what i wanted this forecast to appear as..
so, now the final code:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<DiscMaster.Web.Models.Course>" %> <%@ Import Namespace="System.Xml" %> <script type="text/javascript" src="/scripts/featuredcontentglider.js"> /*********************************************** * Featured Content Glider script- (c) Dynamic Drive DHTML code library (www.dynamicdrive.com) * Visit http://www.dynamicDrive.com for hundreds of DHTML scripts * This notice must stay intact for legal use ***********************************************/ </script> <script type="text/javascript"> featuredcontentglider.init({ gliderid: "forecast", //ID of main glider container contentclass: "glidecontent", //Shared CSS class name of each glider content togglerid: "p-select", //ID of toggler container remotecontent: "", //Get gliding contents from external file on server? "filename" or "" to disable selected: 0, //Default selected content index (0=1st) persiststate: false, //Remember last content shown within browser session (true/false)? speed: 500, //Glide animation duration (in milliseconds) direction: "downup", //set direction of glide: "updown", "downup", "leftright", or "rightleft" autorotate: true, //Auto rotate contents (true/false)? autorotateconfig: [5000, 2] //if auto rotate enabled, set [milliseconds_btw_rotations, cycles_before_stopping] }) </script> <div id="forecast" class="glidecontentwrapper"> <% // used to read the forecast xml System.Xml.XmlDocument doc = new XmlDocument(); // our soon-to-be forecast node collection System.Xml.XmlNodeList nodelist = null; // determine if the forecast is already stored in the cache.. if (Cache[Server.UrlPathEncode(Model.CourseDetail.yr_weather)]!=null) { // .. if so, fetch it doc = (XmlDocument)Cache[Server.UrlPathEncode(Model.CourseDetail.yr_weather)]; } else { // .. and if not, try to consume the source using a reader.. try { System.Xml.XmlTextReader reader = new XmlTextReader(Server.UrlPathEncode(Model.CourseDetail.yr_weather)); doc.Load(reader); // add entry to cache Cache.Add(Server.UrlPathEncode(Model.CourseDetail.yr_weather), doc, null, DateTime.Now.AddMinutes(60), Cache.NoSlidingExpiration, CacheItemPriority.Default, null); } catch (Exception ex) { // just in case something went wrong we allow this to be blank for now.. throw; } } // if all is loaded ok and data is there, simple xpath query to get the forecast data.. if (doc!=null) { if (doc.HasChildNodes) { nodelist = doc.SelectNodes("/weatherdata/forecast/tabular/time"); } } if (nodelist!=null) { if (nodelist.Count>0) { // restruct the nodelist to a queryable list, then group by the day of the forecast, and iterate 'em.. foreach (var day in nodelist.OfType<XmlNode>().GroupBy(n => DateTime.Parse(n.Attributes["from"].Value).ToString("yyyy-MM-dd"))) { // iterate each forecast in the current group (day) foreach (XmlNode node in day) { %> <div class="glidecontent"> <p> <strong><%= DateTime.Parse(node.Attributes["from"].Value).ToString("yyyy-MM-dd HH:MM") %> - <%= DateTime.Parse(node.Attributes["to"].Value).ToString("HH:MM")%></strong> <br /> <img style="float: left;" src='<%= String.Format("/Image.ashx?src=/Content/Media/Icons/Weather/{0}.png&width=64", node["symbol"].Attributes["number"].Value.PadLeft(2,'0')) %>' /> conditions: <%= node["symbol"].Attributes["name"].Value%> <br /> temperature: <%= node["temperature"].Attributes["value"].Value%><sup>o</sup>C <br /> precipitation: <%= node["precipitation"].Attributes["value"].Value%> <br /> wind: <%= node["windSpeed"].Attributes["name"].Value%> - <%= node["windSpeed"].Attributes["mps"].Value%> mps <%= node["windDirection"].Attributes["code"].Value%> </p> </div> <% } } } } %> </div> <div id="p-select" class="glidecontenttoggler"> <a href="#" class="prev"><img border="0" title="previous forecast" src="/Image.ashx?src=/Content/Media/Icons/24x24/previous.png&width=32" /></a><br /><a href="#" class="next"><img border="0" title="next forecast" src="/Image.ashx?src=/Content/Media/Icons/24x24/next.png&width=32" /></a> </div> <div class="forecastfooter"> <small> Weather forecast from <a href="http://www.yr.no" target="_blank">yr.no</a> delivered by<br />the Norwegian Meteorological Institute and the NRK </small> </div>
and the final view:
that’s really all there is to it.. some tweaking of the css and jQuery part to be more what i wanted it to be, but none the less it’s a fairly simple example and could hopefully give you some ideas or lend you some help.
external sources to this article:
- Featured Content Glider script via Dynamic Drive
- Weather forecast data via yr.no
- Weather symbols via yr.no
Regards,
P.
No comments:
Post a Comment