Monday, December 19, 2016

How to upgrade an ASP.NET Core 1.0 app to 1.1

ASP.NET Core 1.1 RTM was announced on November 16, 2016. It is supposed to be the fastest ASP.NET to date.

In this post, I will show you how to upgrade your ASP.NET Core 1.0 web application to ASP.NET Core 1.1.

Let us start by downloading and installing ASP.NET 1.1 RTM.

Installing .NET Core 1.1 RTM

On Windows computers, .NET Core is found under C:\Program Files\dotnet. If you go to that location, this is what you will see:

image

Have a peek at the contents of the sdk folder. You will see something similar to this:

image

The above shows us the actual versions of .NET Core on your computer. Since I have already installed .NET Core 1.1, I have folder “1.0.0-preview2-1-003177”. This is the RTM version of .NET Core 1.1. When you install .NET Core 1.1, you will see this folder “1.0.0-preview2-1-003177”.
Navigate to this location on your Windows computer:

C:\Program Files\dotnet\shared\Microsoft.NETCore.App

Having already installed .NET Core 1.1, this is what the above folder looks like on my computer:

image

If you do not already have .NET Core 1.1, then you will only see folder 1.0.1.

To install .NET Core, go to https://www.microsoft.com/net/download/core. Hover over LTS and Current and read what it says.

image

To download .NET Core 1.1, you must click on Current, then select the appropriate version for your computer and operating system:

image

I chose x64 under the “.NET Core 1.1 SDK – Installer”. At the time of writing, this downloaded a file named dotnet-dev-win-x64.1.0.0-preview2-1-003177.exe. Run the downloaded file to install .NET Core 1.1.

Upgrading an ASP.NET Core 1.0 web app to 1.1

To demonstrate the upgrade process, I will start with an app that I previously developed in ASP.NET Core 1.0. This is what the application looks like when viewed in a browser:

image

Evidence that this application is indeed ASP.NET Core 1.0 is obtained by the existence of only one folder named netcoreapp1.0 under bin/Debug:

image

Step #1

Let us have a look at the global.json file before upgrading to ASP.NET 1.1:
{
  "projects": [ "src", "test" ],
  "sdk": {
    "version": "1.0.0-preview2-003131"
  }
}
Change the SDK version number from "1.0.0-preview2-003131" to “1.0.0-preview2-1-003177”. I copied this exact version from the folder for .NET Core 1.1 located at C:\Program Files\dotnet\sdk.

Step #2

Edit project.json. Change Microsoft.NETCore.App version from “1.0.1” to “1.1.0”  at the top of the project.json file.
image

Still in the project.json file, change “netcoreapp1.0” to “netcoreapp1.1” in the frameworks section.

image

In the command-line, while in the web project folder, run the following commands:
dotnet restore
dotnet build
dotnet ef database update
dotnet run
The third command (dotnet ef database update) is necessary only if your application is database driven.

Viewing the application in a browser results in the same output as before:


image

But, how do we know that we are running in ASP.NET Core 1.1? Well, these are the pieces of evidence that I noticed:

1) When you run “dotnet build”, there is an indication of the version of .NET Core in this command-line output:

Project SQLiteWeb (.NETCoreApp,Version=v1.1) will be compiled because expected outputs are missing
Compiling SQLiteWeb for .NETCoreApp,Version=v1.1
Compilation succeeded.
    0 Warning(s)
    0 Error(s)
2) If you go back to the bin/Debug folder, you will see that there is one more directory for .NET Core 1.1:

image

As you can see, it is not painful to upgrade an ASP.NET Core 1.0 application to 1.1.










Sunday, December 18, 2016

Seeing detailed error message for ASP.NET Core 1.0 app deployed on Azure App Services

I am sure I am not alone in scratching my head when trying to figure out why an ASP.NET Core 1.0 web app deployed  to Azure crashes and does not work. That happened to me earlier today when I attempted to deploy an ASP.NET Core 1.0 web app that uses the SQLite database to Azure. The error message I received (Oops. 500 Internal Server Error | An error occurred while starting the application) was cryptic and not too helpful – see below:

image

This is the generic error that is displayed when web apps have their environment variable set to production or staging.

This bears the question – how does one set the environment variable in Azure App Services to a setting that sheds some light on what the problem is? Well, Here’s what I determined:
The name of the environment variable key that your ASP.NET Core 1.0 app uses can be determined by looking at your project’s Debug properties in Visual Studio 2015:

image

Alternatively, you can peek into Properties/launchSettings.json to see the values for the environment variable in question:

image

This means that the environment variable that controls detailed error messages is ASPNETCORE_ENVIRONMENT. Ideally, the three common values for this variable are Development, Staging and Production.

My next thought is -, how do I set the ASPNETCORE_ENVIRONMENT environment variable on Azure App Services. It turned out quite easy to do.

1) Login to your Azure subscription then click on “App Services” on the left-side.

image

2) Next, click on your web application. In my case it is SQLiteWeb, as shown below:

image

3) On the next blade, click on “Application Settings”:

image

4) On the next blade, scroll further down until you find the “App Settings” section. Add key=ASPNETCORE_ENVIRONMENT and value=Development as shown below:

image

Don’t forget to click on Save when you are done.

Now refresh the page that had a cryptic error and, voila, you can see a more meaningful error message:

image

Even though the error message looks ugly, at least I have something to work on.
BTW, I was able to solve the error by adding the following statement at the bottom of the Configure() method in Startup.cs:

context.Database.Migrate();

My final Configure() method looks like this:
public void Configure(IApplicationBuilder app,
    IHostingEnvironment env,
    ILoggerFactory loggerFactory,
    SchoolContext context)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    if (env.IsDevelopment())
    {
      app.UseDeveloperExceptionPage();
      app.UseBrowserLink();
    }
    else
    {
      app.UseExceptionHandler("/Home/Error");
    }

    app.UseStaticFiles();
    app.UseMvc(routes =>
    {
      routes.MapRoute(
          name: "default",
          template: "{controller=Home}/{action=Index}/{id?}");
    });

    context.Database.Migrate();
    DummyData.Initialize(context);
}

References:

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/error-handling
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments
http://druss.co/2016/01/asp-net-core-1-0-automatic-migrations-entity-framework-7-ef-core-1-0/

Thursday, December 1, 2016

Test driven development (TDD) with xunittest and .NET Core

We will create the test cases for .NET Core application named FizzBuzz. Here’s how it goes. If a number is divisible by 3 then you will call out Fizz. If a number is divisible by 5 then you will call out Buzz. If a number is divisible by 3 and 5 then you will call out FizzBuzz. Otherwise, you will just call out the number itself.

Here are some examples:

2 1 2
4 1 2 Fizz 4
5 1 2 Fizz 4 Buzz
15 1 2 Fizz 4 Buzz Fizz 7 8 Fizz Fuzz 11 Fizz 13 14 FizzBuzz

The above table would represent our four test cases.

Directory & file structure

Create source (src) and test apps with the following directory and file structure:
image

In the root FizzBuzz directory, create a global.json file that contains the following content:
{
  "projects": [
    "src",
    "test"
  ]
}

Creating the business logic project

In a command line, while in the src/FizzBuzzLibrary directory, create the library project files by executing the following command:
dotnet new --type lib
Similarly, in a command line while the test/FizzBuzzTests directory, create the test project files by executing the following command:
dotnet new --type xunittest
If you open the FizzBuzz directory in Visual Studio Code, your directories & files will look like this:

image
 
Rename the src/FizzBuzzLibrary/Library.cs file to src/FizzBuzzLibrary/FizzBuzzMaster.cs. Open src/FizzBuzzLibrary/FizzBuzzMaster.cs in the editor and change the class name from Class1 to FizzBuzzMaster.
Similarly, rename test/FizzBuzzTests/Test.cs to test/FizzBuzzTests/FizzBuzzTestsMaster.cs. Open test/FizzBuzzTests/FizzBuzzTestsMaster.cs in the editor and change the class name from Tests to FizzBuzzTestsMaster.
Open the src/FizzBuzzLibrary/FizzBuzzMaster.cs file in the editor. Change the namespace to FizzBuzzLibrary and replace Method1() with the following method:
public string GetResult(int nmbr) {   
  string result = "";
  return result;
}
You will notice that the above method is destined to fail. This is the fundamental principal of test driven development whereby methods are built to fail.

We should create our test cases. Open test/FizzBuzzTests/FizzBuzzTestsMaster.cs in the editor and replace the Test1() method with the following four test cases:

[Fact]
public void Given2Result12() {
  FizzBuzzMaster fbm = new FizzBuzzMaster();
  var expected = "1 2 ";
  var actual = fbm.GetResult(2);
  Assert.Equal(expected, actual);
}

[Fact]
public void Given4Result12fizz4() {
  FizzBuzzMaster fbm = new FizzBuzzMaster();
  var expected = "1 2 Fizz 4 ";
  var actual = fbm.GetResult(4);
  Assert.Equal(expected, actual);
}

[Fact]
public void Given5Result12fizz4buzz() {
  FizzBuzzMaster fbm = new FizzBuzzMaster();
  var expected = "1 2 Fizz 4 Buzz ";
  var actual = fbm.GetResult(5);
  Assert.Equal(expected, actual);
}

[Fact]
public void Given15Result12fizz4buzzfizz78fizzbuzz11fizzfizz1314fizzbuzz() {
  FizzBuzzMaster fbm = new FizzBuzzMaster();
  var expected = "1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz ";
  var actual = fbm.GetResult(15);
  Assert.Equal(expected, actual);
}
We need to make a reference to the Library project from the test project. This is done by adding the following dependency to the test/FizzBuzzTests/project.json file:
"FizzBuzzLibrary":{
  "target": "project"
}
The dependencies collection in test/FizzBuzzTests/project.json now looks like this:
"dependencies": {
  "System.Runtime.Serialization.Primitives": "4.1.1",
  "xunit": "2.1.0",
  "dotnet-test-xunit": "1.0.0-rc2-192208-24",
  "FizzBuzzLibrary":{
    "target": "project"
  }
}
We have built our preliminary business logic and test cases. In addition, we referenced our business logic application into our test cases application. Now let us test things out.

To restore, build and test Library application, execute the following commands from within the root FizzBuzz directory:
dotnet restore src/FizzBuzzLibrary
dotnet build src/FizzBuzzLibrary
dotnet restore test/FizzBuzzTests
dotnet build test/FizzBuzzTests
It is now time to run the actual tests. This is done by executing the following command also from within the root FizzBuss directory:

dotnet test test/FizzBuzzTests

The test execution shows the following results:

Project FizzBuzzLibrary (.NETStandard,Version=v1.6) was previously compiled. Skipping compilation.
Project FizzBuzzTests (.NETCoreApp,Version=v1.0) was previously compiled. Skipping compilation.
xUnit.net .NET CLI test runner (64-bit win10-x64)
  Discovering: FizzBuzzTests
  Discovered:  FizzBuzzTests
  Starting:    FizzBuzzTests
    Tests.FizzBuzzTestsMaster.Given5Result12fizz4buzz [FAIL]
      Assert.Equal() Failure
                Γåô (pos 0)
      Expected: 1 2 Fizz 4 Buzz
      Actual:
                Γåæ (pos 0)
      Stack Trace:
        D:\scrap\_3973\FizzBuzz\test\FizzBuzzTests\FizzBuzzTestsMaster.cs(24,0): at Tests.FizzBuzzTestsMaster.Given5Result12fizz4buzz()
    Tests.FizzBuzzTestsMaster.Given2Result12 [FAIL]
      Assert.Equal() Failure
                Γåô (pos 0)
      Expected: 1 2
      Actual:
                Γåæ (pos 0)
      Stack Trace:
        D:\scrap\_3973\FizzBuzz\test\FizzBuzzTests\FizzBuzzTestsMaster.cs(12,0): at Tests.FizzBuzzTestsMaster.Given2Result12()
    Tests.FizzBuzzTestsMaster.Given15Result12fizz4buzzfizz78fizzbuzz11fizzfizz1314fizzbuzz [FAIL]
      Assert.Equal() Failure
                Γåô (pos 0)
      Expected: 1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fiz┬╖┬╖┬╖
      Actual:
                Γåæ (pos 0)
      Stack Trace:
        D:\scrap\_3973\FizzBuzz\test\FizzBuzzTests\FizzBuzzTestsMaster.cs(30,0): at Tests.FizzBuzzTestsMaster.Given15Result12fizz4buzzfizz78fizzbuzz11fizzfizz1314fizzbuzz()
    Tests.FizzBuzzTestsMaster.Given4Result12fizz4 [FAIL]
      Assert.Equal() Failure
                Γåô (pos 0)
      Expected: 1 2 Fizz 4
      Actual:
                Γåæ (pos 0)
      Stack Trace:
        D:\scrap\_3973\FizzBuzz\test\FizzBuzzTests\FizzBuzzTestsMaster.cs(18,0): at Tests.FizzBuzzTestsMaster.Given4Result12fizz4()
  Finished:    FizzBuzzTests
=== TEST EXECUTION SUMMARY ===
   FizzBuzzTests  Total: 4, Errors: 0, Failed: 4, Skipped: 0, Time: 0.229s
SUMMARY: Total: 1 targets, Passed: 0, Failed: 1.


Let’s fix all four failed tests by fixing our GetResult() method in src/FizzBuzzLibrary/FizzBuzzMaster.cs. Replace the GetResult() method with the following code:
public string GetResult(int nmbr) {   
  string result = "";

  for (int ndx=1; ndx<nmbr+1; ndx++) {
    if (ndx % 3 == 0 && ndx % 5 ==0) {
      result += "FizzBuzz ";
    } else if (ndx % 5 ==0 ) {
      result += "Buzz ";
    } else if (ndx % 3 ==0 ) {
      result += "Fizz ";                   
    }
    else
      result += ndx.ToString() + " ";
  }

  return result;
}
Build and run your tests again. This should be the outcome after you build and run your tests again:

Project FizzBuzzLibrary (.NETStandard,Version=v1.6) was previously compiled. Skipping compilation.
Project FizzBuzzTests (.NETCoreApp,Version=v1.0) was previously compiled. Skipping compilation.
xUnit.net .NET CLI test runner (64-bit win10-x64)
  Discovering: FizzBuzzTests
  Discovered:  FizzBuzzTests
  Starting:    FizzBuzzTests
  Finished:    FizzBuzzTests
=== TEST EXECUTION SUMMARY ===
   FizzBuzzTests  Total: 4, Errors: 0, Failed: 0, Skipped: 0, Time: 0.161s
SUMMARY: Total: 1 targets, Passed: 1, Failed: 0.


We are happy that all our tests have successfully passed.






















Sunday, November 20, 2016

Continuous deployment of angular-cli Angular 2 app to Azure thru GitHub

In this post, I will show you how to deploy an Angular 2 application on GitHub to Azure. The application will first be pushed to GitHub then we will configure Azure to automatically sync changes from GitHub. This may not be the quickest way to do it, but it does work.

The following are prerequisites:
  • node.js is installed
  • angular-cli is installed
  • git is installed on your computer
  • you have a GitHub account
  • you have an Azure subscription

Creating a sample Angular 2 app

The first step is to create an application named ng2_to_azure. Type the following within a working directory in a terminal windows:

ng new ng2_to_azure

Once the above command completes, you will find the following directory and file structure has been created in a new directory named ng2_to_azure:
image

Change to the newly created directory with:

cd ng2_to_azure

Start the Angular 2 app with this command:

ng serve

If you point your browser to http://localhost:4200. You should see the following web page:

image

Creating production version of Angular 2 app

If you open the .gitignore text file in an editor, you will notice that the /dist directory is excluded. Comment out that line by adding a # so that it looks like this:

image

Save the .gitignore file and exit your editor. We will next produce the production version of our app. This is done by executing the following build command while in the root ng2_to_azure directory:

ng build --prod --aot

The above command transpiles all the TypeScript files JavaScript files and puts the results in the /dist folder. The aot switch builds using ahead-of-time compilation. Have a peek at the contents of the /dist folder:

image

Notice that the main page is index.html. Assuming that your web server is still running, point your browser to http://localhost:4200/dist. The production version of your application will display in the browser:

image

Adding GitHub source control to your application

Go to http://github.com and login into your account.

image

On the right-side, beside "Your repositories", click on the green "New Repository" button.

image

Enter ng2_to_azure for repository name, then click on the green "Create repository" button.

image

We will follow some of the instructions highlighted above. Go to a command-line in the ng2_to_azure directory on your computer. and type in the following commands:

git add .
git commit -m "first commit"
git remote add origin
https://github.com/{github user}/ng2_to_azure.git
git push -u origin master


Note: Make sure you enter your GitHub handle instead of {github user} in the URL above.
Once you have successfully completed the above, you can go back to GitHub in your browser and view all the files in your ng2_to_azure repository:

image

Note that the /dist folder is also contained in the repository.

Continuous deployment on azure

Go to http://portal.azure.com and login into you Azure account.

image

Click on the big + (New) on the top left-side.

image

Click Web App on the next blade.

image
  • Choose an "App name" that is sufficiently unique when combined with domain azurewebsites.net
  • Choose your subscription
  • For "Resource Group" either create a new or use an existing one
  • While configuring "App Service plan/Location", you get to choose which data center you want.
Finally, click on the blue Create button at the bottom of the blade. Once your web app is created, it will appear in the list of your "App Services".

image

Click on the web app you just created.

image

Enter "deploy" in the filter field at the top then select "Deployment Options".

image

On the next blade, click on "Choose Source".

image

Click on GitHub. If this is the first time you connect to GitHub from Azure, you will be asked for your credentials. Once your GitHub credentials are known to Azure then you will see a blade that looks like this:

image

Click on "Choose project" to select the appropriate GitHub repository that you wish to connect Azure with.

image

Click on the Angular 2 repository you previously setup on GitHub. Back in the "Deployment source" blade, click on the blue OK button at the bottom of the blade. If you click on "Deployment options" again, you will determine that Azure is building your app with the following message:

image

Finally, when the build process is complete, you should see the following:

image

Now let us point to our application in the browser. In my case, I tried to access http://ng2azure.azurewebsites.net and this is the response I got:

image

One can guess that the web server found no default page in the root of the web application. To prove my point, we can find out what files we have in the root of the web site. Go back to the Azure portal in your browser and enter the word “Tools” in your filter field:

image

Click on Console. This will take you into the Azure terminal window. Type "dir" to see what is in the root folder.

image

It is obvious that there is no welcome page in the root of the web application. What we need to do is educate Azure that the /dist directory is indeed the root of our web application.

Enter the word "application" into the filter field.

image

Click on Application settings. Under "App settings", add the following

key = Project
value = ./dist

image

Do not forget to click on Save at the top.

image

To get the new configuration to take effect, we must trigger a new deployment. Go back to "Deployment options" and click on Sync so a new deployment is initiated.

image

Once the new deployment is completed, click on your fully qualified web address on azure and you should see that your application is indeed working.

image

If you have a better way of deploying an Angular 2 application to Azure, I would appreciate your letting me know through a comment on this post.

ASP.NET Core MVC + Web API app with EF Core 1.0 & SQLite

This tutorial uses Visual Studio 2015 and ASP.NET Core 1.0.

My intention is to give you a practical introduction into developing ASP.NET Core 1.0 MVC and Web API apps with the SQLite database as an alternative to traditional SQL Server.

A useful utility that comes in handy when working with the SQLite database is SQLiteStudio. Download SQLiteStudio from: http://sqlitestudio.pl/?act=download. Extract the ZIP file and place contents in a separate folder. Run SQLiteStudio.exe.

We will build an ASP.NET Core 1.0 app that uses the following Student entity:

image_thumb1

ASP.NET Core 1.0 MVC project

Create a new ASP.NET Core app in Visual Studio 2015:
  • File >> New >> Project
  • Templates >> Visual C# >> Web
image
  • Select “ASP.NET Web Application (.NET Core)”, name the project SQLiteWeb then click on OK.
image
  • Select “Web Application”, uncheck “Host in the cloud”, then click on OK.

Open the global.json and note the runtime version that will be used by the application:
{
  "projects": [ "src", "test" ],
  "sdk": {
    "version": "1.0.0-preview2-003131"
  }
}

The above indicates that the version of the runtime that is being used is 1.0.0-preview2-003131.
Dependencies are added to the project.json file. Open this file and have a peek at the dependencies section:
"dependencies": {
  "Microsoft.NETCore.App": {
    "version": "1.0.1",
    "type": "platform"
  },
  "Microsoft.AspNetCore.Diagnostics": "1.0.0",
  "Microsoft.AspNetCore.Mvc": "1.0.1",
  "Microsoft.AspNetCore.Razor.Tools": {
    "version": "1.0.0-preview2-final",
    "type": "build"
  },
  "Microsoft.AspNetCore.Routing": "1.0.1",
  "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
  "Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
  "Microsoft.AspNetCore.StaticFiles": "1.0.0",
  "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
  "Microsoft.Extensions.Configuration.Json": "1.0.0",
  "Microsoft.Extensions.Logging": "1.0.0",
  "Microsoft.Extensions.Logging.Console": "1.0.0",
  "Microsoft.Extensions.Logging.Debug": "1.0.0",
  "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
  "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0"
},
Build the application then run it by hitting CTRL F5 to see what it looks like in your browser.

image

This runs your application in IIS Express. Close your browser.

When working with ASP.NET Core 1.0, you will need to go to the command-line interface frequently. Add a command-prompt extension to make it easier. Click on Tools >> Extensions and Updates…

image

Find an extension named “Open Command Line” as shown below.

image

If you have not installed it already, install the above extension.

In solution explorer, right-click on the SQLiteWeb node the choose “Open Command Line” >> “Default (cmd)

image

This opens a regular operating system terminal window. Try out some important .NET Core 1.0 commands.
  1. dotnet --help – this gives you a list of common commands
  2. dotnet restore – restore dependencies specified in the .NET project
  3. dotnet build - Builds a .NET project
  4. dotnet run --help – provides help information about the run command
  5. dotnet new --type --help – shows the types of templates that can be scaffolded. At the time of writing these are: Console, Web, Lib, xunittest.
  6. dotnet new --type web – scaffolds a web template in the current directory
Execute the following command in order to run your web application using another cross-platform web server called Kestrel on port 5000, instead of IIS Express.

dotnet run

Note the following message:

Project SQLiteWeb (.NETCoreApp,Version=v1.0) was previously compiled. Skipping compilation.
Hosting environment: Production
Content root path: D:\scrap\_4976\SQLiteWeb\src\SQLiteWeb
Now listening on:
http://localhost:5000
Application started. Press Ctrl+C to shut down.

Point your browser to http://localhost:5000. You will see the exact same page as before.
Close your browser, close the command-line terminal window and return to Visual Studio 2015.
We will need to add some dependencies in order to use SQLite with Entity Framework Core . Add these dependencies to the project.json file:

"Microsoft.EntityFrameworkCore.Sqlite": "1.0.1",
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"

Add the following to the tools section in the project.json file:
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"

Class Library Project

It is good practice to place all your data models inside a Models folder. Therefore, add a folder called Models. Inside of the Models folder, add a class file named Student.cs. Use the following code for the class file:

public class Student {
  public int Id { get; set; }
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public string School { get; set; }
  public DateTime StartDate { get; set; }
}


Also, to the Models folder, add another class file named SchoolContext.cs with the following class definition code:

public class SchoolContext : DbContext {
  public SchoolContext(DbContextOptions<SchoolContext> options) :base(options)
        { }

  public DbSet<Student> Students { get; set; }
}


We will need to add a connection string for the SQLite database in the SQLiteWebAPI project:
  • Open the appsettings.json file in the SQLiteWebAPI project
  • Add the following section after the Logging block:
"Data": {
  "DefaultConnection": {
    "ConnectionString": "Data Source=school-db.sqlite"
  }
}
We will need to add both Entity Framework and SQLite to the project’s Startup.cs class:
  • Open the Startup.cs file.
  • Add the following code to the ConfigureServices() method just before services.AddMvc();
var connection = Configuration["Data:DefaultConnection:ConnectionString"];
services.AddDbContext<SchoolContext>(options => options.UseSqlite(connection));


The above reads the connection string from the appsettings.json file and passes it on to the SchoolContext class.

Seed Data

Before we carry out code first migrations, let us first create some seed data:
  • In the Models folder, create a class named DummyData.cs.
  • Add the following Initialize() method code inside the DummyData class:
public static void Initialize(SchoolContext db) {
  if (!db.Students.Any()) {
    db.Students.Add(new Student {
      FirstName = "Bob",
      LastName = "Doe",
      School = "Engineering",
      StartDate = Convert.ToDateTime("2015/09/09")
    });
    db.Students.Add(new Student {
      FirstName = "Ann",
      LastName = "Lee",
      School = "Medicine",
      StartDate = Convert.ToDateTime("2014/09/09")
    });
    db.Students.Add(new Student {
      FirstName = "Sue",
      LastName = "Douglas",
      School = "Pharmacy",
      StartDate = Convert.ToDateTime("2016/01/01")
    });
    db.Students.Add(new Student {
      FirstName = "Tom",
      LastName = "Brown",
      School = "Business",
      StartDate = Convert.ToDateTime("2015/09/09")
    });
    db.Students.Add(new Student {
      FirstName = "Joe",
      LastName = "Mason",
      School = "Health",
      StartDate = Convert.ToDateTime("2015/01/01")
    });
    db.SaveChanges();
  }
}

To generate seed data, we will first inject the dependency “SchoolContext context” into the arguments of the Configure() method in Startup.cs. Next, we can make a call to seed the data at the bottom of the Configure() method with the following statement:
      
DummyData.Initialize(context);

Migrations

We are now ready to do some migrations:
  • Compile your application
  • Open a command terminal inside the src\SQLiteWeb folder
  • Add a migration to the project with the following ef command:
dotnet ef migrations add FirstMigration

Notice that class files are created in the Migrations folder.
  • We will then update the database with the following terminal command:
dotnet ef database update

At this point, there will be a file named school-db.sqlite in the src\SQLiteWeb\bin\Debug\netcoreapp1.0 folder. The data will not have been seeded yet because this happens when the application is actually run. 

Creating an MVC UI

Let us seed the data by running your web application in a browser. You should see the same page as we saw earlier. Let us create a UI so that we can see the seeded data.

  • Right-click on the Controllers folder and choose Add >> New Item… >> MVC Controller Class
  • Name the class file StudentController.cs.
  • Replace the class definition with the following code:
public class StudentController : Controller {
  private SchoolContext _context;

  public StudentController(SchoolContext context) {
      _context = context;
  }

  public IActionResult Index() {
      return View(_context.Students.ToList());
  }

  public IActionResult Create() {
      return View();
  }

  [HttpPost]
  [ValidateAntiForgeryToken]
  public IActionResult Create(Student student) {
      if (ModelState.IsValid) {
          _context.Students.Add(student);
          _context.SaveChanges();
          return RedirectToAction("Index");
      }

      return View(student);
  }

}

You’ll notice that the controller takes a SchoolContext as a constructor parameter. ASP.NET dependency injection will take care of passing an instance of SchoolContext into your controller.

The controller contains an Index action, which displays all blogs in the database, and a Create action, which inserts a new student into the database.

Let us add a view for the UI.
  • Create a new folder under Views named Student.
  • Right-click on the newly created Student folder and and select Add >> New Item…
  • Add an “MVC View Page” item and accept the default name index.cshtml.
  • replace the contents of the index.cshtml with the following code:
@model IEnumerable<SQLiteWeb.Models.Student>
@{
  ViewBag.Title = "Students";
}

<h2>@ViewBag.Title</h2>
<p>
  <a asp-controller="Student" asp-action="Create">Create New</a>
</p>

<table class="table">
  <tr>
    <th>Id</th>
    <th>First Name</th>
    <th>Last Name</th>
    <th>School</th>
    <th>Start Date</th>
  </tr>

  @foreach (var item in Model) {
  <tr>
      <td>
        @Html.DisplayFor(modelItem => item.Id)
      </td>
      <td>
        @Html.DisplayFor(modelItem => item.FirstName)
      </td>
      <td>
        @Html.DisplayFor(modelItem => item.LastName)
      </td>
      <td>
        @Html.DisplayFor(modelItem => item.School)
      </td>
      <td>
        @Html.DisplayFor(modelItem => item.StartDate)
      </td>
  </tr>
  }
</table>

  • Let us add a link to the Student controller on the main page of our application. Open _Layout.cshtml under Views/Shared.
  • Paste the following markup in the navigation section around line 36:
<li><a asp-area="" asp-controller="Student" asp-action="Index">Student</a></li>
  • Run the application then click on the Student link. You should see the dummy data that we created.
image
The “Create New” link is currently broken. We need to develop the UI for adding new students
  • Create a “MVC View Page” item create.cshtml under Views/Student.
  • Replace the contents of create.cshtml with the following markup:
@model SQLiteWeb.Models.Student
@{
  ViewBag.Title = "New Blog";
}

<h2>@ViewData["Title"]</h2>
<form asp-controller="Student" asp-action="Create" method="post" class="form-horizontal" role="form">
  <div class="form-horizontal">
    <div asp-validation-summary="All" class="text-danger"></div>
    <div class="form-group">
      <label asp-for="FirstName" class="col-md-2 control-label"></label>
      <div class="col-md-10">
        <input asp-for="FirstName" class="form-control" />
        <span asp-validation-for="FirstName" class="text-danger"></span>
      </div>
    </div>
    <div class="form-group">
      <label asp-for="LastName" class="col-md-2 control-label"></label>
      <div class="col-md-10">
        <input asp-for="LastName" class="form-control" />
        <span asp-validation-for="LastName" class="text-danger"></span>
      </div>
    </div>
    <div class="form-group">
      <label asp-for="School" class="col-md-2 control-label"></label>
      <div class="col-md-10">
        <input asp-for="School" class="form-control" />
        <span asp-validation-for="School" class="text-danger"></span>
      </div>
    </div>
    <div class="form-group">
      <label asp-for="StartDate" class="col-md-2 control-label"></label>
      <div class="col-md-10">
        <input asp-for="StartDate" class="form-control" />
        <span asp-validation-for="StartDate" class="text-danger"></span>
      </div>
    </div>
    <div class="form-group">
      <div class="col-md-offset-2 col-md-10">
        <input type="submit" value="Create" class="btn btn-default" />
      </div>
    </div>
  </div>
</form>

  • Add a new student to the database by running your application and clicking on Student >> Create New.
image

The WebAPI Controller

Let us add a Web API Studentsapi controller to our projects.
  • In the Controllers folder, add a new “Web API Controller Class” named StudentapiController
  • Replace StudentapiController class definition with the following code:
[Route("api/[controller]")]
public class StudentapiController : Controller {
  private SchoolContext _context { get; set; }

  public StudentapiController(SchoolContext context) {
    _context = context;
  }

  // GET: api/student
  [HttpGet]
  public IEnumerable<Student> Get() {
    return _context.Students.ToList();
  }

  // GET api/studentapi/5
  [HttpGet("{id}")]
  public Student Get(int id) {
    return _context.Students.FirstOrDefault(s => s.Id == id);
  }

  // POST api/studentapi
  [HttpPost]
  public void Post([FromBody]Student student) {
    _context.Students.Add(student);
    _context.SaveChanges();
  }

  // PUT api/studentapi/5
  [HttpPut("{id}")]
  public void Put(int id, [FromBody]Student student) {
    _context.Students.Update(student);
    _context.SaveChanges();
  }

  // DELETE api/studentapi/5
  [HttpDelete("{id}")]
  public void Delete(int id) {
    var student = _context.Students.FirstOrDefault(t => t.Id == id);
    if (student != null) {
        _context.Students.Remove(student);
        _context.SaveChanges();
    }
  }
}


  • Hit CTRL-F5 on your keyboard and point your browser to /api/studentapi. You will see the seed data appearing as JSON in the browser:
image_thumb11

In subsequent blog posts I shall discuss