.Net Core

ASP.NET Core Basics: MVC Controller with Entity Framework Core

Last week’s post covered the installation and creation of a new project in ASP.NET Core. This week I will be expanding that existing project to create a basic contact list which will use Entity Framework Core and its scaffolding capabilities to generate the needed files from a model class. This code from last week is being used as a starting point for this post.

Add a Model

To start off I need a class to represent the information for a single contact. In the default setup the proper place to store this type of class is in the Models folder. To add a new class from the Solution Explorer window right click on the Models folder and select Add > Class menu option.

AddClassMenu

This menu choice will bring up the Add New Item dialog defaulted to adding a new class. Enter the name as Contact.cs and click Add.

AddNewItemDialogContact

The following is my resulting Contact after adding the properties of a contact that this application is going to use.

namespace Contacts.Models
{
    public class Contact
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string PostalCode { get; set; }
        public string Phone { get; set; }
        public string Email { get; set; }
    }
}

Scaffolding

Now that the application knows what a Contact looks like we can take advantage of a feature of Entity Framework Core called scaffolding. Scaffolding can be sued to create a number of different setups based on a model, but in this case it I am using it to generate a MVC Controller with views, using Entity Framework which will result in a controller, DbContext and associated MVC razor views being created.

In the Solution Explorer window right click on the Controllers folder and select Add > New Scaffolded Item.

AddNewScaffoldedItemMenu

On the Add Scaffold dialog select MVC Controller with views, using Entity Framework. This is the only option that will create views. Now click the Add button.

AddScaffoldDialog

The Add Controller dialog will be shown next. First select the model that should be the base of the scaffolding operation which is the Contact class for this project. For the data context class option I used the plus (+) button to add a new one since this project doesn’t have an existing data context that I want to use.

AddControllerDialog

After clicking add and letting the process finish the Controllers folder will now contain a ContactsController and in the Models folder there will be ContactsContext. I always move the newly created context out of the Models folder and into the Data folder to match the location used for the ApplicationDbContext.

Entity Framework Migration

Now that the application has a contact model and DbContext it is time to create an entity framework migration which is the mechanism entity framework uses to create and/or migrate a database to match the changes made in the models of an application. Migrations can be added within Visual Studio via the Package Manager Console or from a command prompt using the .NET CLI. I am going to walk through both, but keep in mind you only need to use one.

Package Manager Console

To open the Package Manager Console use the View > Other Windows > Package Manager Console menu. Which show a window that looks like the following.

PackageManagerConsole

To add a migration use run the Add-Migration Init-Contacts -Context ContactsContext command. The Package Manager Console is using powershell so Add-Migration is a command that take a parameter that is the name of the migration which is Init-Contacts in this case. -Context ContactsContext is required in this application because it contains more than one DbContext and the command has to know which DbContext it is working with.

.NET CLI

Open a command prompt and navigate to your project’s directory and then run the dotnet ef migrations add Init-Contacts –context ContactsContext command. This is does exactly the same thing as the Package Manager Console above with just slightly different syntax.

Regardless of which version is used you will see a new Migrations folder added to the root of the project that contains a snapshot of the models referenced by the relevant DbContext as well as a migration file named by using a time stamp plus the migration name.

Automatic Database Migration

In the early stages of a project (or always if it meets your need) it is nice to automatically apply migrations instead of having to do so manually using the package manager console or the .NET CLI. One way to accomplish this is to add a static flag to the constructor of the DbContext in question and if that flag is false then use Database.Migrate() to apply any migrations that the database is missing. Here is an example using my ContatsContext class with the flag named _created.

public sealed class ContactsContext : DbContext
{
    private static bool _created;
    public DbSet<Contact> Contact { get; set; }
    public ContactsContext(DbContextOptions<ContactsContext> options)
        : base(options)
    {
        if (_created) return;
        Database.Migrate();
        _created = true;
    }
}

Add Navigation

At this point you could type in a URL that would take you to the index action of the new ContactsController, but it would be much more useful to add a link to the sites navigation bar to provide an easy way to access the new functionality. The code for the navigation bar can be found in _Layout.cshtml which is located in the Views > Shared folder.

The navigation bar is defined using an unordered list with a class of “nav navbar-nav”. Add a new link to the unorderd list labeled Contact List. This new link needs to point to the index action of ContactsController. ASP.NET Core provides some tag helpers to assist in building links to controller actions. Using the asp-controller and specify “Contacts” as the controller which will resolve to the ContactsController and then use asp-action set to “Index” to point to the index action.

<ul class="nav navbar-nav">
    <li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
    <li><a asp-area="" asp-controller="Contacts" asp-action="Index">Contact List</a></li>
    <li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
    <li><a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a></li>
</ul>

Wrapping Up

Now when the application is run there will be a link for Contact List at the top that will trigger actions in the new controller and backing database table.

Next week I play to take this same project and add a web API end point to it and show how that end point can be verified using Postman.

The code that goes with the post can be found here.

Migration from ASP.NET Core RC2 to RTM

On June 27th .NET Core 1.0 RTM was released which include ASP.NET Core 1.0 and Entity Framework Core 1.0. The links are to the official Microsoft announcement blogs.

Installation

Install instructions can be found at http://dot.net using the Download .NET Core button in the bottom center of the page or use this link to go directly to the install directions. If you are using Visual Studio 2015 then update 3 must be installed before installing .NET Core for Visual Studio which includes the RTM bits plus preview 2 of the related tooling.

After both installers are complete open a command prompt and run the command dotnet –version and verify the version is 1.0.0-preview2-003121.

Global.json

Update the version in the sdk section.

{
  "projects": [ "src", "test" ],
  "sdk": {
    "version": "1.0.0-preview2-003121"
  }
}

Project.json

The following table can be used to find and replace a lot of the changes in this file.

RC2 RTM
1.0.0-rc2-3002702 1.0.0
1.0.0-rc2-final 1.0.0

The run time option for server GC was moved.

Before:
"runtimeOptions": {
  "gcServer": true
}

After:
"runtimeOptions": {
  "configProperties": {
    "System.GC.Server": true
  }
}

A new option is now included in the publish options for “Areas/**/Views”.

Before:
"publishOptions": {
  "include": [
    "wwwroot",
    "Views",
    "appsettings.json",
    "web.config"
  ]
}

After:
"publishOptions": {
  "include": [
    "wwwroot",
    "Views",
    "Areas/**/Views",
    "appsettings.json",
    "web.config"
  ]
}

Finally in the scripts section if you are not using NPM and Gulp then the following change should be made. It is my understanding the choice to remove NPM and Gulp by default was to speed up restores.

Before:
"scripts": {
  "prepublish": [ "npm install", "bower install", "gulp clean", "gulp min" ],
  "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}

After:
"scripts": {
  "prepublish": [ "bower install", "dotnet bundle" ],
  "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}

Here is the full file for reference with NPM left in.

{
  "userSecretsId": "YourSecretsId",

  "dependencies": {
    "Microsoft.NETCore.App": {
      "version": "1.0.0",
      "type": "platform"
    },
    "Microsoft.AspNetCore.Authentication.Cookies": "1.0.0",
    "Microsoft.AspNetCore.Diagnostics": "1.0.0",
    "Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore": "1.0.0",
    "Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0",
    "Microsoft.AspNetCore.Mvc": "1.0.0",
    "Microsoft.AspNetCore.Razor.Tools": {
      "version": "1.0.0-preview1-final",
      "type": "build"
    },
    "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
    "Microsoft.AspNetCore.StaticFiles": "1.0.0",
    "Microsoft.EntityFrameworkCore.SqlServer": "1.0.0",
    "Microsoft.EntityFrameworkCore.Tools": {
      "version": "1.0.0-preview2-final",
      "type": "build"
    },
    "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
    "Microsoft.Extensions.Configuration.Json": "1.0.0",
    "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0",
    "Microsoft.Extensions.Logging": "1.0.0",
    "Microsoft.Extensions.Logging.Console": "1.0.0",
    "Microsoft.Extensions.Logging.Debug": "1.0.0",
    "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0",
    "Microsoft.VisualStudio.Web.CodeGeneration.Tools": {
      "version": "1.0.0-preview2-final",
      "type": "build"
    },
    "Microsoft.VisualStudio.Web.CodeGenerators.Mvc": {
      "version": "1.0.0-preview2-final",
      "type": "build"
    }
  },

  "tools": {
    "BundlerMinifier.Core": "2.0.238",
    "Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final",
    "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final",
    "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final",
    "Microsoft.Extensions.SecretManager.Tools": "1.0.0-preview2-final",
    "Microsoft.VisualStudio.Web.CodeGeneration.Tools": {
      "version": "1.0.0-preview2-final",
      "imports": [
        "portable-net45+win8"
      ]
    }
  },

  "frameworks": {
    "netcoreapp1.0": {
      "imports": [
        "dotnet5.6",
        "portable-net45+win8"
      ]
    }
  },

  "buildOptions": {
    "emitEntryPoint": true,
    "preserveCompilationContext": true
  },

  "runtimeOptions": {
    "configProperties": {
      "System.GC.Server": true
    }
  },

  "publishOptions": {
    "include": [
      "wwwroot",
      "Views",
      "Areas/**/Views",
      "appsettings.json",
      "web.config"
    ]
  },

  "scripts": {
    "prepublish": [ "npm install", "bower install", "gulp clean", "gulp min" ],
    "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
  }
}

Breaking Changes

A list of breaking changes for this release can be found here. The only one I hit was this issue which changes the JSON serializes to use camel case names by default. To restore the previous behavior making the following change in the ConfigureServices function of the Startup class.

Before:
services.AddMvc();

After:
services.AddMvc()
        .AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());

Congratulations

Congratulations to .NET Core teams for hitting RTM! I know there has been some negative things said about the amount of churn in the RC phase of the project, but based on what I feel they made the right choice for the future of the platform. If you don’t already I highly recommend watching the ASP.NET Community Stand-up where you can see a lot of these issues discussed by the team.

In the next few of weeks the team should be releasing a road map of what they are going to be working on next such as SignalR.

.Net CLI Custom Tool

Last week’s post was an overview of the .NET CLI. This week I am going to cover creating a new custom tool for the CLI. This post is going to assume you already has the .NET CLI installed. If not check out last week’s post for instructions.

Getting Started

The tools used by the .NET CLI are just console applications so to begin create a new console application using the CLI with the following commands in a new directory.

dotnet new
dotnet restore

Now that you have a new console application open the new folder up with Visual Studio Code (or the editor of your choice). The tool I am creating will count the files in a project. Very contrived I know, but I wanted to keep this simple and not get distracted by the details of what the tool actually does.

Project.json

The following is the project.json from my file counter tool. The big thing to note is “outputName”: “dotnet-fc” in the buildOptions section. In this example dotnet-fc will make the tool callable from the CLI using dotnet fc. The leading dotnet lets the CLI find the tool and the bit after the dash is the verb that is used with the CLI to execute the tool.

{
  "version": "1.0.0-*",
  "description": "Test creation of a .NET CLI Tool",
  "buildOptions": {
    "emitEntryPoint": true,
    "outputName": "dotnet-fc"
  },
  "dependencies": {
    "Microsoft.NETCore.App": {
      "type": "platform",
      "version": "1.0.0-rc2-3002702"
    }
  },
  "frameworks": {
    "netcoreapp1.0": {}
  }
}

Program.cs

The following is the actual code from the tool that counts the number of files. Again I don’t want this to be the focus of the post, but I am including it for completeness.

using System;
using System.IO;
using System.Linq;

namespace ConsoleApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var fileCount = Directory
                                .EnumerateFiles(Directory.GetCurrentDirectory(), 
                                                "*.*", 
                                                SearchOption.AllDirectories).Count();
            Console.WriteLine($"{Directory.GetCurrentDirectory()} continas {fileCount} files");
        }
    }
}

The console write line is using string interpolation if you have not see it before check out this page.

NuGet

Now that the application is complete use the .NET CLI to create a NuGet package out of it. This functionality is built in to the CLI via the pack command.

dotnet pack

Inside your project directory the NuGet package can be found in the bin directory under either Debug or Release depending on what type of build was done. In my case the project is FileCounter so pack produced FileCounter.1.0.0.nupkg in the bin\Debug directory.

The next step is to add a new package source to your NuGet.Config file which can be found (on Windows) in the C:\Users\YourUser\AppData\Roaming\NuGet directory. In the packageSources section add a new key and value for the directory you want to use for the source of the new tool. The following is my complete NuGet.Config with a new source for “local”.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
	<add key="local" value="C:\NuGetLocal" />
  </packageSources>
</configuration>

Using the New Tool

Open the project that you want to use the new tool with using Visual Studio Code (or any text editor). The new tool will need to be added to the tools section of the project.json file. The following is an example of a full project.json as it exits from using dotnet new with an added tools section.

{
  "version": "1.0.0-*",
  "buildOptions": {
    "emitEntryPoint": true
  },
  "dependencies": {
    "Microsoft.NETCore.App": {
      "type": "platform",
      "version": "1.0.0-rc2-3002702"
    }
  },
"tools": {
    "FileCounter": {
       "version": "1.0.0"
    }
},
  "frameworks": {
    "netcoreapp1.0": {
      "imports": "dnxcore50"
    }
  }
}

Now from the CLI do a dotnet restore and the new tool should be ready to use. In the case of this example you can now run dotnet fc and get a count of the files in your project’s directory.

Lessons Learned

This was the first time I had worked with local NuGet packages and I spent a good bit of time learning where to find the NuGet.Config and the local NuGet caches (C:\Users\YourUser\.nuget\packages and C:\Users\YourUser\.nuget\packages\.tools) were located and the proper edits to make.

The other big thing I would do different the next time around would to be to take advantage of the fact that the .NET CLI will find tools that are on the system path. During development it would have been much simpler than having to go clear the local NuGet caches or change the version number of the tool.

Update

Code used in this post can be found in this GitHub repo.

.NET CLI Overview

In my post on migration from ASP.NET Core RC1 to RC2 I mentioned that there was a move from dnx to the .NET CLI. This post will be an overview this new platform and some of its capabilities.

Installation

If you already have ASP.NET Core RC2 installed then you already have the .NET CLI. If not head over to http://dot.net and click on Download .NET Core (or click here). This should take you to the proper download for your current OS. If you are on Windows and just want to install the command line tools the .NET Core SDK installer can be found here.

Installation Verification

Open a command prompt and run dotnet –version and if all is install and working you should see the version of the CLI you have installed. As of this writing I have version 1.0.0-preview1-002702 installed.

Hello World

Creating a new application that prints hello world to the console can be done without changing any code. First create a new directory and navigate  to the new directory. Next execute the following commands.

dotnet new
dotnet restore
dotnet run

After the last command you should see “Hello World!” printed by a .NET console application that was created with the new command. restore uses project.json (for now) to download the packages need for the application. Finally run compiles and executes the application.

Basic Concepts

You may see the dotnet command referred to as a driver. All this means is that it is used to execute other commands. For example dotnet new is telling the drive to execute the new command (also termed verb). The CLI comes with a set of common commands out of the box that can be extended with more commands via NuGet on per project or on the system path for machine level commands.

Common Commands

The following is a list of common command pull using dotnet help

Command Description
new Initialize a basic .NET project
restore Restore dependencies specified in the .NET project
build Builds a .NET project
publish Publishes a .NET project for deployment (including the runtime)
run Compiles and immediately executes a .NET project
test Runs unit tests using the test runner specified in the project
pack Creates a NuGet package

Adding Commands via NuGet

I am going to add the Entity Framework Core tool to the Hello World application created above as an example. To do this I am using Visual Studio Code, but you can use any editor you would like. All the changes needed will be made in project.json

In the dependencies section add the follow so that the needed packages will be downloaded when the dotnet restore command is run.

"Microsoft.EntityFrameworkCore.Tools": {
  "type": "build",
  "version": "1.0.0-preview1-final"
}

Next add a tool section. The tool section how CLI discovers available commands.

"tools": {
    "Microsoft.EntityFrameworkCore.Tools": {
       "imports": ["portable-net451+win8"],
       "version": "1.0.0-preview1-final"
   }
}

Finally in the frameworks section the imports needs to be change from dnxcore50. This change is needed for Entity Framework Core and may not be required if you are trying to use a different tool. The following is the full frameworks section.

"frameworks": {
  "netcoreapp1.0": {
    "imports": "portable-net451+win8"
  }
}

After running dotnet restore to download the new dependencies dotnet ef can be used to access Entity Framework Core commands. Running dotnet ef without any other arguments will display the Entity Framework Core command help.

                     _/\__
               ---==/    \\
         ___  ___   |.    \|\
        | __|| __|  |  )   \\\
        | _| | _|   \_/ |  //|\\
        |___||_|       /   \\\/\\
Entity Framework .NET Core CLI Commands 1.0.0-preview1-20901
Usage: dotnet ef [options] [command]
Options:
  -h|--help                        Show help information
  -v|--verbose                     Enable verbose output
  --version                        Show version information
  --framework <FRAMEWORK>          Target framework to load
  --configuration <CONFIGURATION>  Configuration under which to load
Commands:
  database    Commands to manage your database
  dbcontext   Commands to manage your DbContext types
  migrations  Commands to manage your migrations
Use "dotnet ef [command] --help" for more information about a command.

Wrapping Up

Here are a couple of good references if you are just getting started. First is the documentation for the .NET CLI which can be found here. The second is this post by Sam Basu.

Keep an eye for a future post on the process of creating new tool that can be used with the .NET CLI.