The year 2016 is the year of the command-line. Several years ago when i was working on the Unix operating system I’ve used many command-line tools such as grep, awk, sed, ed, more, and others. Now the command-line is back. Probably it was used all the time on other platforms, but now it is back on the Microsoft platform.
With this, the .NET Core command-line (CLI) tools are very efficient to work with. These tools are also known by the name dotnet tools, because every option is availalbe with dotnet.
With this blog article I’m showing the options available with dotnet new (available with Preview 2 of the tools).
.NET Core command-line (CLI) Tools
The CLI tools are installed with the .NET Core 1.0 Tools for Visual Studio 2015. You can also install it separately from http://dot.net for different platforms.
The newest versions are available at Github dotnet / cli.
The version I’m using now is the version available with the release of .NET Core 1.0. After the program is installed, you can find it in the folder %Program Files%\dotnet\dotnet.exe.
To see the current version, you can use the argument –version:
> dotnet --version 1.0.0-preview2-003121
Preview 2 of the tools is available with the release of .NET Core 1.0. Later this year (or early next year), when Visual Studio “15” is released, the tools will be released. With the release, the project.json file will be migrated to MSBuild.
Console Applications
Invoking the command dotnet new creates a console application – a Program.cs source file with project.json. You can also supply the –type argument, and pass Console to get the same result. (For –type, there’s also a shortcut -t).
> dotnet new --type Console
The generated project.json looks like this:
{ "version": "1.0.0-*", "buildOptions": { "debugType": "portable", "emitEntryPoint": true }, "dependencies": {}, "frameworks": { "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.0" } }, "imports": "dnxcore50" } } }
With the buildOptions, the emitEntryPoint is defined which means the program contains the Main
method, the entry point to the application. Only when creating library applications, and entry point is not needed.
The debugType defines how the symbol files are generated. The value portable is available for .NET Core projects. Other values are full for traditional Windows-only PDB files, or none.
The frameworks section specifies the frameworks supported by the project. The value must be a valid Target Framework Moniker (TFM). netcoreapp1.0 is a TFM for .NET Core apps, version 1.0.
In my book Professional C# 6 and .NET Core 1.0 I’m adding a TFM for the full .NET Framework for most samples to make sure the application compiles both with .NET Core as well as the .NET Framework.
The dependencies section within the specified framework defines the packages needed when the application is compiled for the framework. Adding packages to the global dependencies section, the packages are needed by all specified frameworks. In case only one framework is specified, it doesn’t matter if the dependencies are added to the framework itself or the global scope.
Here, the dependency Microsoft.NETCore.App is specified. Microsoft.NETCore.App is a metapackage that specifies .NET Core libraries are used. In a previous version of .NET Core it was necessary to speccify every package needed by the application, e.g. the package System.Console when the Console class was used. To make things easier, metapackages include a large list of other packages, and it is not necessary to add every needed package.
Microsoft.NETCore.App 1.0 itself references NETStandard.Library 1.6 among other packages. NETStandard.Library itself is a metapackage that defines the new standard for .NET.
The imports to dnxcore50 is just a helper alias that for using packages that don’t have yet the new, actual TFM names. With dnxcore50 it is possible to reference all packages that list support for this moniker.
An interesting setting of the Microsoft.NEtCore.App dependency is the value for the type: platform. This setting requires the .NET runtime to be installed on the target system. With this, the runtime is shared between applications – like it has been with the .NET Framework. Creating a publish package (using dotnet publish) doesn’t publish the runtime. This type of application is a portable application. Removing this setting and adding runtimes to project.json, a self-contained application can be created that distributes the runtime with the application.
After restoring packages with dotnet restore, the program can be built with dotnet build, and started with dotnet run.
> dotnet restore > dotnet build > dotnet run
Library
To create a library, the command dotnet new –type Lib can be used:
> dotnet new --type Lib
This creates a project.json file without emitEntryPoint, and without a dependency on Microsoft.NETCore.App. The dependency here is on netstandard1.6. Be careful to select the version of .NET Standard with a library. The lower the version number, the more platforms can use this library. The higher the version number, the more APIs are available.
Libraries built with 1.0-1.6 of .NET Standard can be used with .NET Core 1.0. To use the library from a .NET 4.5.1 application, you can use .NET Standard only up to version 1.2. To use the library from a .NET 4.6 application, libraries built with .NET Standard 1.0 to 1.3 are ok. To use the library from a Universal Windows Platform application, you can use the standard up to version 1.4.
{ "version": "1.0.0-*", "buildOptions": { "debugType": "portable" }, "dependencies": {}, "frameworks": { "netstandard1.6": { "dependencies": { "NETStandard.Library": "1.6.0" } } } }
Web Application
For ASP.NET Core Web applications, the –type option is Web.
> dotnet new --type Web
This not only creates a single source file with project.json. Instead, this project consists of a larger project.json file referencing all the libraries needed with ASP.NET MVC 6 including controllers and views, as well as configuration for Bower, NPM, and Gulp.
{ "userSecretsId": "aspnet-WebApplication-0799fe3e-6eaf-4c5f-b40e-7c6bfd5dfa9a", "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-preview2-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.Sqlite": "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": { "Microsoft.AspNetCore.Razor.Tools": { "version": "1.0.0-preview2-final", "imports": "portable-net45+win8+dnxcore50" }, "Microsoft.AspNetCore.Server.IISIntegration.Tools": { "version": "1.0.0-preview2-final", "imports": "portable-net45+win8+dnxcore50" }, "Microsoft.EntityFrameworkCore.Tools": { "version": "1.0.0-preview2-final", "imports": [ "portable-net45+win8+dnxcore50", "portable-net45+win8" ] }, "Microsoft.Extensions.SecretManager.Tools": { "version": "1.0.0-preview2-final", "imports": "portable-net45+win8+dnxcore50" }, "Microsoft.VisualStudio.Web.CodeGeneration.Tools": { "version": "1.0.0-preview2-final", "imports": [ "portable-net45+win8+dnxcore50", "portable-net45+win8" ] } }, "frameworks": { "netcoreapp1.0": { "imports": [ "dotnet5.6", "dnxcore50", "portable-net45+win8" ] } }, "buildOptions": { "debugType": "portable", "emitEntryPoint": true, "preserveCompilationContext": true }, "runtimeOptions": { "configProperties": { "System.GC.Server": true } }, "publishOptions": { "include": [ "wwwroot", "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%" ] }, "tooling": { "defaultNamespace": "WebApplication" } }
Unit Test
There’s another type to create an inital project: xunittest:
> dotnet new --type xunittest
With this type, a class containing a unit test as well as project.json that references the testRunner xunit is created:
dotnet new –type xunittest
{ "version": "1.0.0-*", "buildOptions": { "debugType": "portable" }, "dependencies": { "System.Runtime.Serialization.Primitives": "4.1.1", "xunit": "2.1.0", "dotnet-test-xunit": "1.0.0-rc2-192208-24" }, "testRunner": "xunit", "frameworks": { "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.0" } }, "imports": [ "dotnet5.4", "portable-net451+win8" ] } } }
Now, after building the executable, the unit test can run using dotnet test:
> dotnet restore > dotnet build > dotnet test
With .NET Core you are not restricted to use XUnit. Other test runners, for example MSTest, can be specified as well. XUnit was the first unit testing framework available for .NET Core applications, and is also used by the .NET Core teams.
Programming Languages
Other than the project type, it’s also possible to specify the programming language with dotnet new. With the option –lang (or the shortcut -l), either F# or C# can be specfiied as programming languages. Using F# it’s currently only possible to create console applications:
> dotnet new --type Console --lang F#
This is the Hello, World! for F#:
// Learn more about F# at http://fsharp.org open System [<EntryPoint>] let main argv = printfn "Hello World!" printfn "%A" argv 0 // return an integer exit code
The project.json for F# also includes the F# compiler and the tools configuration for the F# compiler to allow compiling the program with the dotnet tools:
{ "version": "1.0.0-*", "buildOptions": { "emitEntryPoint": true, "compilerName": "fsc", "compile": { "includeFiles": [ "Program.fs" ] } }, "dependencies": { "Microsoft.FSharp.Core.netcore": "1.0.0-alpha-160509" }, "tools": { "dotnet-compile-fsc": { "version": "1.0.0-preview2-*", "imports": [ "dnxcore50", "portable-net45+win81", "netstandard1.3" ] } }, "frameworks": { "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.0" } }, "imports": [ "portable-net45+win8", "dnxcore50" ] } } }
Because F# for .NET Core is not released yet, and the packages for F# are not available on the main NuGet server, this project-based NuGet.Config file specifies the source for the F# packages:
<?xml version="1.0" encoding="utf-8"?> <configuration> <packageSources> <!--To inherit the global NuGet package sources remove the <clear/> line below --> <clear /> <add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" /> <add key="fsharp-daily" value="https://www.myget.org/F/fsharp-daily/api/v3/index.json" /> <!-- Location of dotnet-compile-fsc tool --> <add key="dotnet-cli" value="https://dotnet.myget.org/F/dotnet-cli/api/v3/index.json" /> </packageSources> </configuration>
Summary
The dotnet new command can be used to start console applications, libraries, Web applications, and unit tests. While this offers an easy start to create applications without other tools needed, a future version of dotnet new will be even more powerful. Instead of just specifying the type with -t, -t stands for template. With templates a lot more starting points can be offered, and it’s also possible to create custom templates.
Have fun with programming and learning!
Christian
More Information
Professional C# 6 and .NET Core 1.0
My workshops
Microsoft documentation for project.json
Microsoft documentation for .NET Core App Types
Microsoft documentation for .NET Standard Library
dotnet-new enhancements
Related Information
What’s in there for ASP.NET Core Web Developers
.NET Core 1.0 is Released!
Portable Library, you’ll not be missed
Professional C# 6 and .NET Core 1.0 RC2
Dependency Injection with .NET Core
Professional C# 6 and .NET Core 1.0
MS-DOS Command Line: image from © Fabricio Rauen | Dreamstime.com IBM PC Operating System
7 thoughts on “dotnet-new”