Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Weather App with MVVM, IoC, DI and API

5.00/5 (9 votes)
29 Jul 2016CC (ASA 2.5)5 min read 21.1K  
This is an application made for Windows (Universal) 10 devices made with MVVM, IoC-containers and dependency injection. There is also an API from Yahoo and SQLite service.

Introduction

I've made an application that works on Windows Universal 10 devices. It gives the forecast for several cities in this world by an API (Application Programming Interface) from Yahoo. It contains the MVVM (Model View View-Model) pattern (more specific MVVM light library) and IoC (Inversion of Control) architectures. I use also SQLite (Structured Query Language lite) database for storing the search results. But what are there? Here comes some information:

MVVM (Model View View-Model)

Architecture of MVVMMVVM is a software architectural pattern and it's built in three parts like it said. In your project, you have three parts: models, views and view-models like show on image behind.

The models give access the database, but for this project, I use APIs from Yahoo mapped into the folder Repositories.

View-models contains ICommands and some binding properties. All view models inherit form ViewModelBaseClass where the interface INotifyPropetyChanged has been implemented.

The last part are the views. This contains the XAML pages and data templates. The last one is stored into the folder DataTemplates.

Each part is communicated with each other:

  • The views with the view models
  • The view models with the models (and repositories)
  • The repositories access the API (or another data source)

In theory, this is correct, but in practical situations communicate the view also with the models. This must be for the data bindings of the element properties to the model properties.

On the image, there is also a fourth part named unit tests. These are tests you can make for testing your code. This is not implemented in the project and not explained in this article.

IoC-Container (Inversion of Control Container)

IoC containers are containers with basic functionality needed to register and resolve instances. For the project, we go use the SimpleIoc class from MVVM light. The methods we go use in these project are:

Name Description
Register<TClass>(Boolean)

Registers a given type with the possibility for immediate creation of the instance.

GetInstance<TService>()

Provides a way to get an instance of a given type. If no instance had been instantiated before, a new instance will be created. If an instance had already been created, that same instance will be returned.

Remark: If the class is not registered, the method will return null.

For more information and methods, you can read the documentation on mvvmlight.net.

There is also a default constructor without parameters that initializes a new instance of the SimpleIoc class.

Dependency Injection or DI

Dependency injection is a way of working that allow you to make code independent of the class where you are working on. For this, you can use interfaces. They defined only the signature of the methods, properties and variables. An example you can use is to use a dummy class when developing or a web service when deploying. Here, you've a code example:

C#
public interface IDataSource
{
    IEnumarble<object> Get(); // used for get all the objects
}

public class DummySource : IDataSource
{
    public IEnumarble<object> Get()
    {
        return new List<object> {
            new { Letter = "A", Number = "1" },
            new { Letter = "A", Number = "1" }
        }
    }
}

public class WebSource : IDataSource
{
    public IEnumarble<object> Get()
    {
        //return all objects of a web service 
    }
}

On the place where you call the Get() method, it doesn't matter what the class is. It could be the dummy class or the webservice.

Note: On the place where you call the method, don't use the classes but use the interface like code below:

C#
IDataSource source = new DummySource();
IEnumarble<object> dummyData = source.Get();

source = new WebSource();
IEnumarble<object> webData = source.Get();

This code will work because the variable source, is independent from the class DummySource and WebSource because I've made a "wrapper" interface named IDataSource that has a signature of the methods.

Building the App

Making Of the Solution

In the solution, I've made three projects named:

  1. Data contains repositories for accessing the API. Download the NuGet Newtonsoft.Json package for this project.
  2. Models contain the classes we need.
  3. UWP what stands for Universal Windows 10 Project and has the following folders:
    • Assets is default folder added in the project and contains images for the logo into the Windows store.
    • DataTemplates for store data templates
    • Pages contains the pages we go use
    • Services contains the IoC container
    • ViewModels contains the view models and one folder
      • core for storing the core data

We also need some NuGet packages you can download from the NuGet manager. For the data project is this Newtonsoft.JSON and for the UWP project, we need MvvmLight.

Making of the Pages

If the UWP project is made, you see next items into that project:

  • Properties contain the properties of that project.
  • References contain the references needed for that project.
  • The folders we've just created.
  • App.xaml contains important recourses and information about your project.
  • MainPage.xaml is the first page that is shown when the application runs.
  • Package.appxmanifest
  • project.json
  • Wheater.UWP_TemporaryKey.pfx

First, we need MainPage.xaml.

Use of APIs (Application Programming Interface)

An API or Application Programming Interface is a service for getting routines, protocols, tools or data powered by other instances (like Yahoo) that software programmers can access into their programs, applications and websites. But can find by robots, Dominica, drones and much more.

The First URL We Need

First of all, we must access the API from Yahoo to get the data from. The URL (Uniform Recourse Locator) that we go use is this:

https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.
forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places%20where%20text%3D%22@placemame%22)
&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys

I found the URL on developer.yahoo.com/weather/. You see the parameter q which is a SQL statement:

SQL
SELECT *
FROM weather.forecast
WHERE woeid 
IN (SELECT woeid
    FROM geo.places
    WHERE text = @placemame)

This will go select all the fields of the table weather.forecast where woeid (WOEID stands for Where On Earth IDentifier) is equal to the value of the select from the table geo.places where the text field is equal to variable @placename. This variable must have a value so that the URL is valid in this case, is this a string or for saying it in SQL language is this from the type nvarchar or text depending on the used SQL language by Yahoo.

In the URL above, you can also see a second parameter called format. For this example, we go use JSON (JavaScript Object Notation) as receiving value.

Convert JSON Code to C# Classes

If you navigate to the URL, you see this JSON code. Here, you've the forecast from March 1st, 2016 from Meenen, Belgium:

JavaScript
{  
   "query":{  
      "count":1,
      "created":"2016-03-01T17:31:15Z",
      "lang":"en-US",
      "results":{  
         "channel":{  
            "title":"Yahoo! Weather - Meenen, BE",
            "link":"http://us.rd.yahoo.com/dailynews/rss/weather/Meenen__BE/
                      *http://weather.yahoo.com/forecast/FRXX4403_f.html",
            "description":"Yahoo! Weather for Meenen, BE",
            "language":"en-us",
            "lastBuildDate":"Tue, 01 Mar 2016 6:00 pm CET",
            "ttl":"60",
            "location":{  
               "city":"Meenen",
               "country":"Belgium",
               "region":""
            },
            "units":{  
               "distance":"mi",
               "pressure":"in",
               "speed":"mph",
               "temperature":"F"
            },
            "wind":{  
               "chill":"37",
               "direction":"200",
               "speed":"20"
            },
            "atmosphere":{  
               "humidity":"93",
               "pressure":"29.83",
               "rising":"0",
               "visibility":"3.73"
            },
            "astronomy":{  
               "sunrise":"7:28 am",
               "sunset":"6:30 pm"
            },
            "image":{  
               "title":"Yahoo! Weather",
               "width":"142",
               "height":"18",
               "link":"http://weather.yahoo.com",
               "url":"http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif"
            },
            "item":{  
               "title":"Conditions for Meenen, BE at 6:00 pm CET",
               "lat":"50.8",
               "long":"3.12",
               "link":"http://us.rd.yahoo.com/dailynews/rss/weather/Meenen__BE/
                       *http://weather.yahoo.com/forecast/FRXX4403_f.html",
               "pubDate":"Tue, 01 Mar 2016 6:00 pm CET",
               "condition":{  
                   "code":"26",
                   "date":"Tue, 01 Mar 2016 6:00 pm CET",
                   "temp":"45",
                   "text":"Cloudy"
               },
               "description":"\n<img src=\"http://l.yimg.com/a/i/us/we/52/26.gif\"/>
                        <br />\n<b>Current Conditions:</b><br />\nCloudy, 45 F<BR />\n<BR />
                        <b>Forecast:</b><BR />\nTue - Showers Late. High: 48 Low: 42<br />
                        \nWed - PM Rain/Wind. High: 48 Low: 36<br />\nThu - Showers/Wind. 
                        High: 44 Low: 34<br />\nFri - Showers. High: 45 Low: 31<br />
                        \nSat - PM Showers. High: 46 Low: 33<br />\n<br />\n
                        <a href=\"http://us.rd.yahoo.com/dailynews/rss/weather/Meenen__BE/
                        *http://weather.yahoo.com/forecast/FRXX4403_f.html\">
                        Full Forecast at Yahoo! Weather</a><BR/><BR/>\n(provided by 
                        <a href=\"http://www.weather.com\" >The Weather Channel</a>)<br/>\n",
               "forecast":[  
                  {  
                     "code":"45",
                     "date":"1 Mar 2016",
                     "day":"Tue",
                     "high":"48",
                     "low":"42",
                     "text":"Showers Late"
                  },
                  {  
                     "code":"12",
                     "date":"2 Mar 2016",
                     "day":"Wed",
                     "high":"48",
                     "low":"36",
                     "text":"PM Rain/Wind"
                  },
                  {  
                     "code":"11",
                     "date":"3 Mar 2016",
                     "day":"Thu",
                     "high":"44",
                     "low":"34",
                     "text":"Showers/Wind"
                  },
                  {  
                     "code":"11",
                     "date":"4 Mar 2016",
                     "day":"Fri",
                     "high":"45",
                     "low":"31",
                     "text":"Showers"
                  },
                  {  
                     "code":"39",
                     "date":"5 Mar 2016",
                     "day":"Sat",
                     "high":"46",
                     "low":"33",
                     "text":"PM Showers"
                  }
               ],
               "guid":{  
                  "isPermaLink":"false",
                  "content":"FRXX4403_2016_03_05_7_00_CET"
               }
            }
         }
      }
   }
}

Of course, you could make the correct C# classes manually, but on the internet, you have some easy tools that do this for you. One of them is json2csharp.com (only to C#) or jsonutils.com (many other languages) that convert all the code for you. Import the classes to your project by copy paste them and rename RootObject to YahooWeather.

Use the of API in the App

Make a new class into the data project named WebRepo and place this code for use of the API.

C#
public class WebRepo
{
    public static async YahooWeather GetData(string placename)
    {
        try
        {
            using (HttpClient client = new HttpClient())
            {
                string url = $@"https://query.yahooapis.com/v1/public/yql?q=select%20
                             *%20from%20weather.forecast%20where%20woeid%20in%20
                             (select%20woeid%20from%20geo.places%20where%20text%3D%22
                             {placemame}%22)&format=json&env=store%3A%2F%2Fdatatables.org
                             %2Falltableswithkeys";

                string yahooGeoJSON = await client.GetStringAsync(url);
                return JsonConvert.DeserializeObject<YahooWeather>(yahooGeoJSON); 
            }
        }
        catch
        {
            return null;
        }
    }
}

Later, we'll make dependency injection for this class.

License

This article, along with any associated source code and files, is licensed under The Creative Commons Attribution-ShareAlike 2.5 License