I have recently found out that Google has its own weather feed. The data is structured perfectly for what I want to do, and the following will show how I went about creating a custom weather web part. I will be adding properties for the user to select if they want the Current Conditions or Tomorrow’s Forecast and the City they live in. (For now these will only be South African cities.)
1. Create the Project in Visual Studio
Open up visual studio and select to create a new Visual Web Part project under the SharePoint > 2010 templates, enter a name and click OK. On the next window enter your site URL and click Finish.
For purposes of keeping my projects tidy I have renamed my Web Part, the user control and the class files to more appropriate names.
2. Set up the user control display
I have added the following to my WeatherWebPartUserControl.ascx file that will render the data:
<style type="text/css">
.wwp-container { width: 200px; text-align: center; font-family:Arial; font-size:12px; }
.wwp-city { font-size:14px; font-weight:bold; }
.wwp-error { color:Red; }
</style>
.wwp-container { width: 200px; text-align: center; font-family:Arial; font-size:12px; }
.wwp-city { font-size:14px; font-weight:bold; }
.wwp-error { color:Red; }
</style>
<div class="wwp-container">
<asp:Label runat="server" ID="lblCity" CssClass="wwp-city"></asp:Label><br />
<asp:Label runat="server" ID="lblDate" CssClass="wwp-date"></asp:Label><br />
<asp:Image runat="server" ID="lblImage" CssClass="wwp-image"></asp:Image><br />
<asp:Label runat="server" ID="lblTemp" CssClass="wwp-temperature"></asp:Label> -
<asp:Label runat="server" ID="lblCondition" CssClass="wwp-condition"></asp:Label>
<asp:Label runat="server" ID="lblError" CssClass="wwp-error"></asp:Label>
</div>
<asp:Label runat="server" ID="lblCity" CssClass="wwp-city"></asp:Label><br />
<asp:Label runat="server" ID="lblDate" CssClass="wwp-date"></asp:Label><br />
<asp:Image runat="server" ID="lblImage" CssClass="wwp-image"></asp:Image><br />
<asp:Label runat="server" ID="lblTemp" CssClass="wwp-temperature"></asp:Label> -
<asp:Label runat="server" ID="lblCondition" CssClass="wwp-condition"></asp:Label>
<asp:Label runat="server" ID="lblError" CssClass="wwp-error"></asp:Label>
</div>
3. Update the Web Part class
In your web part class file you are going to add properties for the web part that will display when you edit the web part in your page. These settings make it easy for users to control how the web part works:
Here's the code:
// enums for the values of the drop downs
public enum CityEnum { None, Johannesburg, Cape_Town, Durban, Pretoria, Bloemfontein };
public enum ForeCastDayEnum { Today, Tomorrow };
public enum CityEnum { None, Johannesburg, Cape_Town, Durban, Pretoria, Bloemfontein };
public enum ForeCastDayEnum { Today, Tomorrow };
// public properties
public static CityEnum City;
public static ForeCastDayEnum ForeCastDay;
public static CityEnum City;
public static ForeCastDayEnum ForeCastDay;
// these settings tell the web part how to display the controls
[Category("Settings"), Personalizable(PersonalizationScope.Shared), WebBrowsable(true), WebDisplayName("City"),
DefaultValue("None"), WebDescription("Select a city")]
public CityEnum _City
{
get { return City; }
set { City = value; }
}
[Category("Settings"), Personalizable(PersonalizationScope.Shared), WebBrowsable(true), WebDisplayName("City"),
DefaultValue("None"), WebDescription("Select a city")]
public CityEnum _City
{
get { return City; }
set { City = value; }
}
// these settings tell the web part how to display the controls
[Category("Settings"),
Personalizable(PersonalizationScope.Shared), WebBrowsable(true), WebDisplayName("Forecast Day"),
DefaultValue("Today"), WebDescription("Select a city")]
public ForeCastDayEnum _ForeCastDay
{
get { return ForeCastDay; }
set { ForeCastDay = value; }
}
[Category("Settings"),
Personalizable(PersonalizationScope.Shared), WebBrowsable(true), WebDisplayName("Forecast Day"),
DefaultValue("Today"), WebDescription("Select a city")]
public ForeCastDayEnum _ForeCastDay
{
get { return ForeCastDay; }
set { ForeCastDay = value; }
}
4. Update the User Control class
The class of the user control is where most of the processes happen. Here the methods are contained for accessing the RSS data and transforming it into displayable data. Below are the methods that I used. Comments are in line.
public const string _webUrl = "http://www.google.com/";
protected void Page_Load(object sender, EventArgs e)
{
lblError.Text = string.Empty;
try
{
WeatherWebPart.CityEnum selectedCity = WeatherWebPart.City;
{
lblError.Text = string.Empty;
try
{
WeatherWebPart.CityEnum selectedCity = WeatherWebPart.City;
// check if a city has been selected
if (selectedCity == WeatherWebPart.CityEnum.None)
{
throw new Exception("No city has been selected from the web part settings.");
}
else
{
GetWeatherData(selectedCity);
}
}
catch (Exception ex)
{
lblError.Text = ex.Message;
}
}
if (selectedCity == WeatherWebPart.CityEnum.None)
{
throw new Exception("No city has been selected from the web part settings.");
}
else
{
GetWeatherData(selectedCity);
}
}
catch (Exception ex)
{
lblError.Text = ex.Message;
}
}
private void GetWeatherData(WeatherWebPart.CityEnum city)
{
// format the url
string url = String.Format(_xmlUrl, city.ToString().Replace("_", " "));
{
// format the url
string url = String.Format(_xmlUrl, city.ToString().Replace("_", " "));
// create the xmlreader
XmlTextReader reader = new XmlTextReader(url);
XmlTextReader reader = new XmlTextReader(url);
// load the reader into an xmldocument
XmlDocument doc = new XmlDocument();
doc.Load(reader);
XmlDocument doc = new XmlDocument();
doc.Load(reader);
// get the root node
XmlNode rootNode = doc.SelectSingleNode("/xml_api_reply/weather");
XmlNode rootNode = doc.SelectSingleNode("/xml_api_reply/weather");
// get the forecast data
string cityName = rootNode.SelectSingleNode("forecast_information/city").Attributes["data"].Value;
DateTime forecastDate = Convert.ToDateTime(rootNode.SelectSingleNode("forecast_information/forecast_date").Attributes["data"].Value);
string cityName = rootNode.SelectSingleNode("forecast_information/city").Attributes["data"].Value;
DateTime forecastDate = Convert.ToDateTime(rootNode.SelectSingleNode("forecast_information/forecast_date").Attributes["data"].Value);
// check if the web part displays today or tomorrows weather
if (WeatherWebPart.ForeCastDay == WeatherWebPart.ForeCastDayEnum.Today)
{
ShowToday(rootNode, cityName, forecastDate);
}
else
{
ShowTomorrow(rootNode, cityName, forecastDate);
}
}
if (WeatherWebPart.ForeCastDay == WeatherWebPart.ForeCastDayEnum.Today)
{
ShowToday(rootNode, cityName, forecastDate);
}
else
{
ShowTomorrow(rootNode, cityName, forecastDate);
}
}
private void ShowTomorrow(XmlNode rootNode, string cityName, DateTime forecastDate)
{
// get tomorrows conditions
string tomorrowCondition = rootNode.SelectSingleNode("forecast_conditions[2]/condition").Attributes["data"].Value;
string tomorrowHigh = rootNode.SelectSingleNode("forecast_conditions[2]/high").Attributes["data"].Value;
string tomorrowLow = rootNode.SelectSingleNode("forecast_conditions[2]/low").Attributes["data"].Value;
string tomorrowIcon = _webUrl + rootNode.SelectSingleNode("forecast_conditions[2]/icon").Attributes["data"].Value;
string temperature = String.Format("{0}°C - {1}°C", tomorrowLow, tomorrowHigh);
{
// get tomorrows conditions
string tomorrowCondition = rootNode.SelectSingleNode("forecast_conditions[2]/condition").Attributes["data"].Value;
string tomorrowHigh = rootNode.SelectSingleNode("forecast_conditions[2]/high").Attributes["data"].Value;
string tomorrowLow = rootNode.SelectSingleNode("forecast_conditions[2]/low").Attributes["data"].Value;
string tomorrowIcon = _webUrl + rootNode.SelectSingleNode("forecast_conditions[2]/icon").Attributes["data"].Value;
string temperature = String.Format("{0}°C - {1}°C", tomorrowLow, tomorrowHigh);
UpdateWebPartDisplay(cityName, tomorrowCondition, forecastDate.AddDays(1), temperature, tomorrowIcon);
}
}
private void ShowToday(XmlNode rootNode, string cityName, DateTime forecastDate)
{
// get the current conditions
string currentCondition = rootNode.SelectSingleNode("current_conditions/condition").Attributes["data"].Value;
string currentTemperature = rootNode.SelectSingleNode("current_conditions/temp_c").Attributes["data"].Value + "°C";
string currentIcon = _webUrl + rootNode.SelectSingleNode("current_conditions/icon").Attributes["data"].Value;
{
// get the current conditions
string currentCondition = rootNode.SelectSingleNode("current_conditions/condition").Attributes["data"].Value;
string currentTemperature = rootNode.SelectSingleNode("current_conditions/temp_c").Attributes["data"].Value + "°C";
string currentIcon = _webUrl + rootNode.SelectSingleNode("current_conditions/icon").Attributes["data"].Value;
UpdateWebPartDisplay(cityName, currentCondition, forecastDate, currentTemperature, currentIcon);
}
}
private void UpdateWebPartDisplay(string city, string condition, DateTime date, string temperature, string iconUrl)
{
lblCity.Text = city;
lblCondition.Text = condition;
lblDate.Text = date.ToLongDateString();
lblTemp.Text = temperature;
lblImage.ImageUrl = iconUrl;
}
{
lblCity.Text = city;
lblCondition.Text = condition;
lblDate.Text = date.ToLongDateString();
lblTemp.Text = temperature;
lblImage.ImageUrl = iconUrl;
}
5. Deploy the web part and install it on the page.
You can deploy the web part by simply right-clicking your project file and clicking Deploy. The solution will deploy to the URL that you specified in the setup stages of the project.
Here is the final look of the web part: