.NET Core

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.