Introduction
I am a full-stack web programmer for the State Department. We work with AngularJS 1.2 mixed with WEB API, WCF and SQL Server - our own hybrid architecture.
It is how I learned this tech. But I wanted to create other Angular based projects, some to help my friends with their hobbies (feral Cats), others to simply solidify my AngularJS understanding - just before I take the leap into AngularJS 2.0…
So I created lots of CRUD apps, and I like the John Papa project structure - so this post is about building an AngularJS CRUD project using the MVC and WEBAPI template, and Entity Framework
Project Requirements
The project will be based on this table at the website wikipedia. This is a table that lists countries by population and captures the change by year in population.
Scope of Step #1
This step simply gets the database up and running.
Data Model
In this project example, I am going to use the Entity Framework Database First - using Microsoft SQL Server.
Scripts
The database scripts are as follows:
CREATE TABLE COUNTRY(
COUNTRYID int IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
COUNTRY varchar(100) NULL,
CONTINENTIAL_REGIONID int NULL,
STATISTICAL_REGIONID int NULL
)
GO
CREATE TABLE UN_CONTINENTAL_REGION(
CONTINENTIAL_REGIONID int IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED ,
CONTINENTIAL_REGION varchar(250) NULL
)
GO
CREATE TABLE UN_STATISTICAL_REGION(
STATISTICAL_REGIONID int IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
STATISTICAL_REGION varchar(250) NULL
)
CREATE TABLE dbo.[POPULATION](
POPULATIONID int IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED ,
COUNTRYID int NULL,
YEARID int NULL,
POPULATION int NULL
)
GO
CREATE TABLE YEAR_DOMAIN(
YEARID int NOT NULL PRIMARY KEY CLUSTERED
)
GO
ALTER TABLE COUNTRY WITH CHECK ADD CONSTRAINT FK_COUNTRY_UN_CONTINENTAL_REGION
FOREIGN KEY(CONTINENTIAL_REGIONID) REFERENCES
UN_CONTINENTAL_REGION (CONTINENTIAL_REGIONID)
GO
ALTER TABLE COUNTRY CHECK CONSTRAINT FK_COUNTRY_UN_CONTINENTAL_REGION
GO
ALTER TABLE COUNTRY WITH CHECK ADD CONSTRAINT FK_COUNTRY_UN_STATISTICAL_REGION
FOREIGN KEY(STATISTICAL_REGIONID) REFERENCES
UN_STATISTICAL_REGION (STATISTICAL_REGIONID)
GO
ALTER TABLE COUNTRY CHECK CONSTRAINT FK_COUNTRY_UN_STATISTICAL_REGION
GO
ALTER TABLE POPULATION WITH CHECK ADD CONSTRAINT FK_POPULATION_COUNTRY
FOREIGN KEY(COUNTRYID)
REFERENCES COUNTRY (COUNTRYID)
GO
ALTER TABLE POPULATION CHECK CONSTRAINT FK_POPULATION_COUNTRY
GO
ALTER TABLE POPULATION WITH CHECK ADD CONSTRAINT FK_POPULATION_YEAR_DOMAIN
FOREIGN KEY(YEARID) REFERENCES YEAR_DOMAIN (YEARID)
GO
ALTER TABLE POPULATION CHECK CONSTRAINT FK_POPULATION_YEAR_DOMAIN
GO
These scripts will create five tables. COUNTRY, UN_CONTINENTAL_REGION,POPULATION,YEAR_DOMAIN and UN_STATISTICAL_REGION.
Probably overkill, but this is for illustration of multiple technologies in a very simple application.
Need some data scripts to populate the database:
INSERT INTO YEAR_DOMAIN
(YEARID) VALUES(2015);
INSERT INTO YEAR_DOMAIN
(YEARID) VALUES(2016);
INSERT INTO YEAR_DOMAIN
(YEARID) VALUES(2017);
INSERT INTO UN_CONTINENTAL_REGION
(CONTINENTIAL_REGION) VALUES('ASIA');
INSERT INTO UN_CONTINENTAL_REGION
(CONTINENTIAL_REGION) VALUES('AMERICAS');
INSERT INTO UN_CONTINENTAL_REGION
(CONTINENTIAL_REGION) VALUES('AFRICA');
INSERT INTO UN_CONTINENTAL_REGION
(CONTINENTIAL_REGION) VALUES('EUROPE');
INSERT INTO UN_CONTINENTAL_REGION
(CONTINENTIAL_REGION) VALUES('OCEANIA');
INSERT INTO UN_STATISTICAL_REGION
(STATISTICAL_REGION) VALUES('Eastern Asia')
INSERT INTO UN_STATISTICAL_REGION
(STATISTICAL_REGION) VALUES('Southern Asia')
INSERT INTO UN_STATISTICAL_REGION
(STATISTICAL_REGION) VALUES('Northern America')
INSERT INTO UN_STATISTICAL_REGION
(STATISTICAL_REGION) VALUES('South-Eastern Asia')
INSERT INTO UN_STATISTICAL_REGION
(STATISTICAL_REGION) VALUES('South America')
INSERT INTO UN_STATISTICAL_REGION
(STATISTICAL_REGION) VALUES('Australia and New Zealand')
DECLARE @CNREGID INT, @STATREGID INT
SELECT @CNREGID=CONTINENTIAL_REGIONID FROM
UN_CONTINENTAL_REGION WHERE CONTINENTIAL_REGION='ASIA'
SELECT @STATREGID=STATISTICAL_REGIONID FROM
UN_STATISTICAL_REGION WHERE STATISTICAL_REGION='Eastern Asia'
INSERT INTO COUNTRY
(COUNTRY, CONTINENTIAL_REGIONID,STATISTICAL_REGIONID)
VALUES('CHINA',@CNREGID,@STATREGID)
SELECT @STATREGID=STATISTICAL_REGIONID FROM
UN_STATISTICAL_REGION WHERE STATISTICAL_REGION='Southern Asia'
INSERT INTO COUNTRY
(COUNTRY, CONTINENTIAL_REGIONID,STATISTICAL_REGIONID)
VALUES('INDIA',@CNREGID,@STATREGID)
SELECT @STATREGID=STATISTICAL_REGIONID FROM
UN_STATISTICAL_REGION WHERE STATISTICAL_REGION='South-Eastern Asia'
INSERT INTO COUNTRY
(COUNTRY, CONTINENTIAL_REGIONID,STATISTICAL_REGIONID)
VALUES('INDONESIA',@CNREGID,@STATREGID)
SELECT @CNREGID=CONTINENTIAL_REGIONID FROM
UN_CONTINENTAL_REGION WHERE CONTINENTIAL_REGION='AMERICAS'
SELECT @STATREGID=STATISTICAL_REGIONID FROM
UN_STATISTICAL_REGION WHERE STATISTICAL_REGION='Northern America'
INSERT INTO COUNTRY
(COUNTRY, CONTINENTIAL_REGIONID,STATISTICAL_REGIONID)
VALUES('UNITED STATES',@CNREGID,@STATREGID)
SELECT @STATREGID=STATISTICAL_REGIONID FROM
UN_STATISTICAL_REGION WHERE STATISTICAL_REGION='South America'
INSERT INTO COUNTRY
(COUNTRY, CONTINENTIAL_REGIONID,STATISTICAL_REGIONID)
VALUES('BRAZIL',@CNREGID,@STATREGID)
SELECT @CNREGID=CONTINENTIAL_REGIONID FROM
UN_CONTINENTAL_REGION WHERE CONTINENTIAL_REGION='OCEANIA'
SELECT @STATREGID=STATISTICAL_REGIONID FROM
UN_STATISTICAL_REGION WHERE STATISTICAL_REGION='Australia and New Zealand'
INSERT INTO COUNTRY
(COUNTRY, CONTINENTIAL_REGIONID,STATISTICAL_REGIONID)
VALUES('AUSTRALIA',@CNREGID,@STATREGID)
DECLARE @COUNTRYID INT;
SELECT @COUNTRYID=COUNTRYID FROM COUNTRY WHERE COUNTRY='CHINA'
INSERT INTO dbo.[POPULATION] (COUNTRYID,YEARID,POPULATION)
VALUES(@COUNTRYID,2015,1376048943)
INSERT INTO dbo.[POPULATION] (COUNTRYID,YEARID,POPULATION)
VALUES(@COUNTRYID,2016,1382323332)
SELECT @COUNTRYID=COUNTRYID FROM COUNTRY WHERE COUNTRY='INDIA'
INSERT INTO dbo.[POPULATION] (COUNTRYID,YEARID,POPULATION)
VALUES(@COUNTRYID,2015,1311050527)
INSERT INTO dbo.[POPULATION] (COUNTRYID,YEARID,POPULATION)
VALUES(@COUNTRYID,2016,1326801576)
SELECT @COUNTRYID=COUNTRYID FROM COUNTRY WHERE COUNTRY='UNITED STATES'
INSERT INTO dbo.[POPULATION] (COUNTRYID,YEARID,POPULATION)
VALUES(@COUNTRYID,2015,321773631)
INSERT INTO dbo.[POPULATION] (COUNTRYID,YEARID,POPULATION)
VALUES(@COUNTRYID,2016,324118787)
SELECT @COUNTRYID=COUNTRYID FROM COUNTRY WHERE COUNTRY='INDONESIA'
INSERT INTO dbo.[POPULATION] (COUNTRYID,YEARID,POPULATION)
VALUES(@COUNTRYID,2015,257563815)
INSERT INTO dbo.[POPULATION] (COUNTRYID,YEARID,POPULATION)
VALUES(@COUNTRYID,2016,260581100)
SELECT @COUNTRYID=COUNTRYID FROM COUNTRY WHERE COUNTRY='BRAZIL'
INSERT INTO dbo.[POPULATION] (COUNTRYID,YEARID,POPULATION)
VALUES(@COUNTRYID,2015,207847528)
INSERT INTO dbo.[POPULATION] (COUNTRYID,YEARID,POPULATION)
VALUES(@COUNTRYID,2016,209567920)
SELECT @COUNTRYID=COUNTRYID FROM COUNTRY WHERE COUNTRY='AUSTRALIA'
INSERT INTO dbo.[POPULATION] (COUNTRYID,YEARID,POPULATION)
VALUES(@COUNTRYID,2015,23968973)
INSERT INTO dbo.[POPULATION] (COUNTRYID,YEARID,POPULATION)
VALUES(@COUNTRYID,2016,24309330)
Scope of Step #2
This step is to get the Visual Studio Solution created.
Visual Studio
One of my colleagues loves to do his web development in JetBrains WebStorm - he swears by it, but I am a life long Visual Studio junkie. As of this writing, I am coding this post using Visual Studio 2017 Community Edition - a first for me, I usually use Professional or Enterprise, but heck, the Community version is so well loaded I love it.
Creating The Project
Open Visual Studio.
- Create New Project.
- When the dialog appears, select Web from the Installed Templates treeview. The middle list will populate, with varying options. Please select ASP.NET Web Application (.NET Framework)
Select a Name, I am picking WorldPopulation along with a location to place the solution.
When the next dialog pops up, among the templates - select Empty BUT look at the checkboxes below. We need to add in some CORE References. Make sure to check MVC and Web API.
- Do not select Add Unit Tests - we will do that but will not use the VisualStudio.TestTools.UnitTesting - rather we will use NUnit.
So, what are those other templates? Lots of tutorials simply skip explaining that. I will take a shot at explaining so you can have an understanding of what you are NOT doing at this point in time.
Note: Also see ASP.NET Web Application Projects and Web Application Projects versus Web Site Projects in Visual Studio.
The Empty template is simply what the name says, a empty web project, bare bones. This template creates an ASP.NET web application that includes a Web.config file, but no other files. Use this project template when you do not require the functionality built into the standard template.
The Web Forms template is server based web applications. All the code resides in the IIS server and gets rendered to the client. It is older technology and not used much for modern development.
According to Microsoft, it is:
Use this project template to create a web application that is based on ASP.NET Web Forms pages and that includes the following functionality. You can choose not to use any of these features when they are not required for your application.
- A master page.
- A cascading style sheet.
- Login security that uses the ASP.NET membership system.
- Ajax scripting that uses jQuery.
- Navigation that uses a menu control.
By default, the ASP.NET Web Application project template includes the following:
- Folders to contain membership pages, client script files, and cascading style sheet files.
- A data folder (App_Data), which is granted permissions that allow ASP.NET to read and write to it at run time.
- A master page (the Site.master file).
- Web pages named Default.aspx, Contact.aspx, and About.aspx. These content pages are based on the default master.
- A global application class (Global.asax file).
- A Web.config file.
- A Packages.config file.
- For more information, see ASP.NET Web Application Projects and Web Application Projects versus Web Site Projects in Visual Studio.
The MVC template, that is Microsoft’ Model-View-Controller template. There are many incarnations of this approach, MVVM, etc., but basically the View (what you see in the web browser) is separate from the Controller (logic) and the Model (data). That is a simplistic explanation.
Use this project template to create web applications that use a model-view-controller pattern, using the ASP.NET MVC 3 release. The MVC pattern helps separate the different aspects of the application (input logic, business logic, and UI logic), while providing a loose coupling between these elements. In addition, this project template promotes test-driven development (TDD).
The Web API is what my friend Van told me once is “Microsoft’ replacement for WCF”. It is much easier to implement, lightweight, flexible. More on this later.
The Single Page Application is a design where there is a single web page that the user sees but portions of the page can load as needed.
When selecting those templates the Solution takes on a predefined structure and loads a lot of predefined files to get the developer up and running quickly. If CORE References is selected for MVC then components needed to do MVC applications are added but the structure of the solution is not populated with a lot of predefined components which a developer doesn’t necessarily need.
WorldPopulation Project
Now that the WorldPopulation (or whatever you called your own implementation of the solution) has been created, it should have one project with the same name.
That project should have 5 Folders:
- App_Data
- App_Start
- Controllers
- Models
- Views
The App_Start folder will have two files in it
- RouteConfig.cs
- WebApiConfig.cs
These are critical to how our application will work. More on that later.
Now we need to add two more projects to the solution.
- WorldPopulation.EF (for Entity Framework, or maybe Datalayer)
- WorldPopulation.UnitTests
Adding Projects
Add Unit Test Project
- In the Solution Explorer scroll to the top, select Solution WorldPopulation.
- Right-click the WorldPopulation solution.
- When the context-menu pops up, select Add.
- When the second context-menu expands, select New Project.
- In the template selector, change to Visual C#.
- In the middle listing of templates - select Class Library (.NET Framework)
- In the Name enter WorldPopulation.EF
- Press OK
Add Unit Test Project
- In the Solution Explorer scroll to the top, select Solution WorldPopulation.
- Right-click the WorldPopulation solution.
- When the context-menu pops up, select Add.
- When the second context-menu expands, select New Project.
- In the template selector, change to Visual C#.
- In the middle listing of templates - select Class Library (.NET Framework)
- In the Name enter WorldPopulation.UnitTests
- Press OK
NuGet Packages
For this example, I am going to use NuGet. I know that Bower and NPM has more recent updates, but for some of the non-web portions NuGet is awesome (plus I like it).
- In the Solution Explorer scroll to the top, select Solution WorldPopulation.
- Right-click the WorldPopulation solution.
- When the context-menu pops up, select Manage NuGet Packages for Solution.
- Click Browse at the top.
NuGet Package |
WorldPop |
WorldPop.EF |
WorldPop.UnitTests |
Entity Framework |
X |
X |
X |
NLog |
X |
X |
X |
NLog.Config |
X |
X |
X |
NUnit |
|
|
X |
NUnit3TestAdapter |
|
|
X |
AngularJS.Core |
X |
|
|
AngularJS.Route |
X |
|
|
bootstrap |
X |
|
|
FontAwesome |
X |
|
|
lodash |
X |
|
|
jQuery |
X |
|
|
toastr |
X |
|
|
jQuery may already installed by other packages like Bootstrap or by the MVC references. Select jQuery in the NuGet package manager and choose the highest available version, then select update if the installed version is below thehighest available one.
When the NuGet package installation step is completed, you will see several additional folders in the WorldPopulation Project:
- Content
- Fonts
- Scripts
Content Folder
This folder mainly contains CSS related files, style sheets.
Fonts
The name is self-descriptive. The customized fonts provided by the Font Awesome libraries are stored within this folder.
Scripts
JavaScript files, AngularJS, Moment.JS, jQuery, etc., all are stored in this folder.
The other NuGet packages such as NLog or Entity Framework are added to the project references.
Scope of Step #3
In this step, we will create the Data Context by connecting to the database and retrieving the model into Visual Studio.
Project WorldPopulation.EF
- Select the WorldPopulation.EF Project.
- Right click the project and click Add on the popup context menu.
- Select New Folder, and enter Interfaces.
- Repeat steps 1-3, only enter Models instead of Interfaces for the new folder name this time.
- Select the Models folder you just created.
- Right-click and select Add from the first context menu, then New Item from the second.
- Select Data from the templates category on the left, then when it is filtered select ADO.NET Entity Data Model.
- For the name enter WPModel. Then click *Add.
- When the next dialog opens, select EF Designer from database.
- Click Next.
- In the Choose Your Data Connection dialog, enter the SQL Server connection information where you created the tables in Step #1.
- Let the settings be the default for the App.Config in my case, my SQL Server database was named DEV so the name of the connection string in App.Config is
DEVEntities
.
- In the next dialog, Choose Your Database Objects and Settings -we are only selecting the tables. Expand the tables, schema. Select:
TABLE NAME |
COUNTRY |
POPULATION |
UN_CONTINENTAL_REGION |
UN_STATISTICAL_REGION |
YEAR_DOMAIN |
Additional Options |
Yes/No |
Pluralize or Singularize Generated Object Names |
Yes |
Include Foreign Key Columns in the Model |
Yes |
Import selected Stored Procedures and functions into the entity model |
No |
MODEL NAMESPACE DEVModel
Remember DEV is my database name, so whatever you choose will be here
- Click Finish
Visual Studio will chug along as it reads the database, getting the model and generates the classes.
When it is done, you will see a visual representation of the SQL Server tables and their relationships in an EDMX file within the Models folder (remember how I had you select it before you started adding the ADO.NET Entity Data Model).
Under the file WPModel.tt you will see the class files for each table in the database.
Under the file WPModel.Context.tt is the WPModel.Context.cs this is the datacontext. I am not going to spend a lot of time explaining this, but you need to read more on this from the MSDN or EntityFramework Tutorial
Scope of Step #4
We need to create our Repository, a tiny one.
We will be working in the WorldPopulation.EF Project. We will be implementing the Implementing the Repository and Unit of Work Patterns in an ASP.NET MVC Application (9 of 10) which basically is
“The repository pattern is an abstraction. It’s purpose is to reduce complexity and make the rest of the code persistent ignorant. As a bonus it allows you to write unit tests instead of integration tests.”
Repository Pattern Resources
Steps to Pattern Implementation
- Select WorldPopulation.EF Project.
- Select the Interfaces Folder.
- Right click the context menu, click Add select Class.
- Enter IRepository.cs. Click OK.
- Open the file IRepository.cs. Modify
class IRepository
to public interface IRepository
.
The interface should be similar to the following:
using WorldPopulation.EF.Models;
using System.Collections.Generic;
namespace WorldPopulation.EF.Interfaces
{
public interface IRepository
{
List GetCountries();
COUNTRY GetCountry(int countryID);
}
}
- Select the Models Folder.
- Right click the context menu, click Add select Class.
- Enter Repository.cs. Click OK.
- We are creating the Repository Pattern and implementing the Interface above in the folder Models in the file named Repository.cs.
- Be sure to add the following namespace reference at the beginning of the file:
- WorldPopulation.EF.Interfaces;
- Type the following code into the file Repository.cs :
using WorldPopulation.EF.Interfaces;
using System.Collections.Generic;
namespace WorldPopulation.EF.Models
{
public class Repository : IRepository
{
private DEVEntities dbConn;
public Repository()
{
dbConn=new DEVEntities();
}
public List<COUNTRY> GetCountries()
{
throw new NotImplementedException();
}
public COUNTRY GetCountry(int countryID)
{
throw new NotImplementedException();
}
}
}
Scope of Step #5
Now we get into the grit.
I still consider myself new to [TDD]TDD (Test-Driven Development).
Update Unit Test
- Add reference to WorldPopulation.EF project.
- Select WorldPopulation.UnitTests. Rename the file Class1.cs to DatalayerUnitTests.cs.
- Open the file DatalayerUnitTests.cs
- Add
using NUnit.Framework;
to class.
- Above the class name
public class DatalayerUnitTests
add the attribute [TestFixture]
.
- Create private member
private IRepository repo;
You will need to add a reference to the namespace using WorldPopulation.EF.Interfaces;
.
- Create a new void method named
Setup()
with the attribute [Setup]
.
- Add a method named
public void Setup()
just below the [Setup]
attribute. In this method add the following line:
repo=new Repository();
You will need to import using WorldPopulation.EF.Models;
namespace.
- Now create our first failing unit test.
[Test]
public void GetCountries_ExpectNone()
{
repo.GetCountries();
Assert.That(repo!=null);
}
NOTE This unit test as written will fail. When you open the repo.GetCountries()
implementation, the code is
public List<COUNTRY> GetCountries()
{
throw new NotImplementedException();
}
Technically, we should be using a MOCK Interface for this but I am short on time so I am going to violate TDD and have the Unit Test become a Integration Test by accessing the data.
Modify the implementation as follows:
public List<COUNTRY> GetCountries()
{
return dbConn.COUNTRies.ToList();
}
Scope of Step #6
Switch to the WorldPopulation Project.
- Select Controllers folder.
- Select Add from the context-menu.
- Select Controller… from the second context-menu.
- Select Web API 2 Controller - Empty* then press Add.
- When the next dialog appears type WorldPopulation and the new controller name should be WorldPopulationController.
- Press the Add button.
- You should see a new file added into the folder Controllers with the name WorldPopulationController.cs.
- When the file opens, expand the curly braces.
- Create a Controller Constructor to instantiate the IRepository interface. You may need to add a reference to the WorldPopulation.EF project
private IRepository repo;
public WorldPopulationController()
{
repo=new Repository();
}
- Now to create a method that will be used by the presentation layer (WEB SITE).
- Below the constructor, type the following attribute (type a few spaces first)
[HttpGet]
- Below that attribute type
[ActionName("GetCountries")]
- Now type below that attribute, type in:
public IEnumerable<COUNTRY> GetCountries()
{
return repo.GetCountries();
}
The entire function should look like:
[HttpGet]
[ActionName("GetCountries")]
public IEnumerable<COUNTRY> GetCountries()
{
return repo.GetCountries();
}
Scope of Step #7
Step #7 will begin to add some basic navigation components to the main web project. A HomeController a basic layout page and the default index.cshtml page.
Starting with the HomeController
Controller classes in AMVC are used to prepare the Model that will be mapped to a view for a particular resource. In this example, AMVC created the following Home Controller that will be used to return the default view for our application.
- Select Controllers folder.
- Select Add from the context-menu.
- Select Controller… from the second context-menu.
- Select MVC 5 Controller - Empty then press Add*.
- When the next dialog appears type Home and the new controller name should be HomeController.
- Press the Add button.
- You should see a new file added into the folder Controllers with the name HomeController.cs.
- Open the *HomeController.
You should see the following:
public ActionResult Index()
{
return View();
}
Now we are going to add some view to the project.
- Select the Views folder. Right-Click and choose the Add from the context-menu.
- Select MVC 5 Layout Page (Razor). In the popup, select _LayoutPage as the file name.
- Paste the following code into the new _LayoutPage.cshtml file:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - My ASP.NET Application</title>
<link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
<link href="~/Content/bootstrap.min.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
@Html.ActionLink("World Population", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav"></ul>
</div>
</div>
</div>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>© @DateTime.Now.Year - WorldPopulation</p>
</footer>
</div>
<script src="~/Scripts/jquery-3.1.1.min.js"></script>
<script src="~/Scripts/bootstrap.min.js"></script>
</body>
</html>