Today’s header image was created by kazu end, the original source for the image is available here

Exciting News!

Last week Scott Hunter and Scott Hanselman announced the release of .NET Core 2.0 preview 1, mid presentation.

My suspicion is that they knew this would knock my sleep cycle out of whack and did it anyway. It’s the only explanation 😛

There’s a long list of changes in .NET Core 2.0 and ASP.NET Core 2.0. I’m going to try and cover some of the most significant and interesting changes that were announced at Build 2017. I’ll then go into more detail with some of them over a series of posts. So stay tuned.

.NET Core 2.0… Kind of

The most exciting thing to come out of Build 2017

at least, for me

was the announcement of .NET Core 2.0.

What was actually announced and released was .NET Core 2.0 preview 1, which is more of a taste of what’s to come, as it is not an RTM release and is not ready for enterprise apps to be built in.

You can get the installer for the .NET Core 2.0 preview here, but keep reading as there are some things that you’ll need to know.

what with it being an early access, preview build and all that jazz.

I’m all about the side-by-side

Scott Hanselman, https://channel9.msdn.com/Events/Build/2017/B8048

As with the previous releases of .NET Core (and, by the looks of it, the future of Microsoft’s products), the 2.0 preview can be installed side-by-side with the current releases of .NET Core.

Say you’re already in the process of building an application with .NET Core 1.0.4, you can still install the .NET Core 2.0 preview 1, and not have to upgrade your pre-existing code base. There’s a slight bit of futzing required when creating projects from templates in the command line, though, but I’ll go into that in a moment.

Related Visual Studio Announcements

Along side .NET Core 2.0 preview 1, Microsoft also announced Visual Studio 2017 Update 3 preview

This is known internally as Visual Studio 15.3, because version numbers don’t have to make sense

also the full release version of Visual Studio for Mac, both of which have support for the new .NET Core 2.0 preview 1 features.

I’ll be putting together a post going into both of these in more detail very soon.

Caveat – Visual Studio and .NET Core 2.0 preview 1

.NET Core 2.0 preview 1 is not supported by Visual Studio 2017 Update 2 (known as 15.2). To create and build .NET Core 2.0 applications, Visual Studio 2017 Update 3 preview is required. This will install side-by-side with Visual Studio 2017 Update 2, however, and shouldn’t affect Visual Studio 2017 Update 2.

You’ll need a fair amount of hard drive space to have them both installed, though.

Visual Studio 2017 Preview 3 Taskbar Icon
The shaded in icon is Visual Studio 2017 Preview 3
Caveat – Visual Studio for Mac and .NET Core 2.0 Preview 1

The full version of Visual Studio for Mac has issues when opening, building and running .NET Core 1.1 applications if the only version of the .NET Core SDK that you have installed is installed is version 2.0 preview. This is because .NET Core 2.0 preview does not contain version 1.1 of the runtime.

There are two ways of fixing this:

  • Edit the csproj manually to target either netcoreapp2.0 or netstandard2.0
  • Use the .NET Core 2.0 preview command line interface to generate the correct csproj file

More information can be found at this GitHub page

.NET Standard 2.0 Preview

If you need a quick reminder on .NET Standard and what it is, I’d recommend that you read my article on it from last year.

The other massive thing for us .NET Core developers is the release of .NET Standard 2.0 preview. I’ll go into it a little more in a few moments, but this is an extremely impressive slide from Scott Hanselman and Scott Hunter’s talk “Three Runtimes, One Standard… .NET Standard: All in Visual Studio 2017

NET Standard 2.0 preview announce slide
Source: https://sec.ch9.ms/sessions/c1f9c808-82bc-480a-a930-b340097f6cc1/build/2017/B8001.pptx

20,000 new APIs! Just think about that for a second. That’s a massive number. So massive in fact, that days before Build, Microsoft announced (a little prematurely, it has been seen) that .NET Core has evolved a little faster than .NET Standard.

Here is a message, left by Scott Hanselman on the GitHub issue which was used to announce .NET Core’s rapid evolution, that was meant to clarify what was actually meant by the issue:

Think about it this way. WPF isn’t netstandard2.0, it knows it’s on net461+ and that’s OK. It’s optimized, but it can reference netstandard libs. ASP.NET Core 2.0 is optimize[d] for Core 2.0 but it can reference shared libraries. Xamarin is the same.

.NET Core is side by side and it’s moving fast. It’s WAY faster than .NET (Full) Framework can move which is good. By building ASP.NET Core 2.0 on top of .NET Core 2.0 (which, remember, is a SUPERSET of .NET Standard) that means stuff can be built faster than NetFx or even Netstandard.

NetCore > Net Standard > NetFx when it comes to development speed and innovation.

Point is, if you are doing new work, netstandard20. If you have older net461+ libraries, MOST of those can be referenced under ASP.NET Core 2.0.

ASP.NET Core 1.1 which runs on .NET Framework will be fully supported for a year after we release 2.0. That workload is fully supported thru at least July of 2018.

The remaining large gaps missing in .NET Core 2 are System.DirectoryServices and System.Drawing. We are working to have a Windows compat pack which would enable both of those on .NET Core on Windows this summer.

Scott Hanselman – https://github.com/aspnet/Home/issues/2022#issuecomment-299536123

Since then, Microsoft has issued a statement (via Miguel de Icaza, who is the head of the Mono and Xamarin teams) to The Register stating that ,NET Framework was not going to be left in the dust.

“I would love to clear up that. I want to hide my face. The .NET Core 2.0 that’s coming, the one that they baked for Build, it’s a preview, and they discovered that they had a number of problems that they couldn’t address fast enough on .NET Framework. So the packages that went out only support running ASP.NET Core 2.0 on .NET Core 2.0. We’ll fix this, and we will run on .NET Framework.”

Miguel de Icaza on retargeting of ASP.NET Core 2 from .NET Standard 2.0 to .NET Core 2.0 – https://www.theregister.co.uk/2017/05/11/microsoft_asp_net_core_2_0/

It’s worth taking a look through both the original GitHub issue and what Miguel had to say, to ensure that you understand what’s happening.

So what’s included in .NET Standard 2.0? Quite a lot, it turns out:

Net Standard 2.0 included APIs slide
Source: https://sec.ch9.ms/sessions/c1f9c808-82bc-480a-a930-b340097f6cc1/build/2017/B8001.pptx

The most exciting thing about .NET Standard 2.0 is that it’s baked into the .NET Core 2.0 preview. So all of the APIs listed in the above image are now accessible in .NET Core 2.0.

On top of all of that, Microsoft have released a NuGet package which can be used to allow a .NET Core application to communicate with a .NET Frameowrk 4.7 class library (as long as it complies with .NET Standard).

This is covered at the 6 and a half minute mark of the two Scott’s talk

Where Can I Get The 2.0 preview Installer?

As I mentioned earlier, the installer for the .NET Core 2.0 preview can be found here. The installer for the SDK contains both the SDK and the runtime.

I’ll come back to that in a moment, too

Which leads me onto one of the more interesting things in the .NET Core 2.0 preview release notes:

The ‘generic’ Linux binary archives are new for the 2.0 release. This package contains binaries which are compatible with Linux distros and versions supported by .NET Core. This will also enable you to experiment with Distros not present on the supported list but are libc compatible.

https://github.com/dotnet/core/blob/master/release-notes/2.0/2.0.0-preview1.md

Technically, as long as a Linux distribution is libc compatible, it can run .NET Core 2.0. I’ll let that sink in for a second.

Think back to the 2001 when Steve Balmer called Linux a cancer, could any of us have envisioned one of Microsoft’s core

unintentional pun

technologies not only being ported to (pretty much) all of the popular Linux distributions, not only running on embedded hardware which doesn’t run Windows, and not only running on MacOS, but also being open source?

me either

.NET Core 2.0 preview Features

Let’s take a look at what we get for using .NET Core 2.0 preview over 1.0.4 (which is the current long term support version).

Aside from the stuff I’ve mentioned already

seriously, scroll back up and take another look

we get a whole host of new stuff.

Unified ASP.NET Core Package

technically this is an ASP.NET Core 2.0 change, but I’ll include it here

In previous versions of ASP.NET Core, we had to explicitly include all of the features of ASP.NET Core that we wanted access to. Things like MVC, Entity Framework Core, Static Files, Routing, Logging, etc.

By way of example, here is part of the csproj for my dwCheckApi project (which runs on .NET Core 1.0.4):

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Routing" Version="1.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.*" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.*" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.*" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.*" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.*" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.*" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.*" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.*" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="1.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="1.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.1">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="1.1.0">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
</ItemGroup>

And here is the same section of the csproj, but for a version with the unified ASP.NET Core pacakge:

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-*" />
</ItemGroup>

We no longer have to track down the individual API packages for functionality of ASP.NET Core that we want to include, we just need to include Microsoft.AspNetCore.All because it includes it all for us.

Runtime Package Store

Previously when we’ve built and deployed .NET Core applications, we’ve had to choose between two options:

  • A framework-dependent deployment (FDD)
  • A self-contained deployment (SCD)

you can read more about these two options in my post on publishing to Digital Ocean

Both of these build options produced, frankly, massive builds containing dlls for each of the packages that had been referenced in the application. However (and working in tandem with the Unified ASP.NET Core package), we can create smaller builds of our application by utilising the Runtime Package Store.

This is how Microsoft describe it:

The runtime package store enables creating a precompiled cache of common libraries which can be centrally provisioned and not deployed to every application reducing deployment size and time.

https://github.com/dotnet/core/blob/master/release-notes/2.0/2.0.0-preview1.md#runtime-package-store

The two Scotts showed that a .NET Core 1.0.4 application which had a publish profile of over 16 megabytes of files is reduced to ~2.6 megabytes when using Runtime Package Store in .NET Core 2.0.

Smaller builds means less time pushing to the cloud, which means smaller bills (and reduced deployment times). Which makes us all happier.

Side-by-Side Development

I touched on this earlier, but because the .NET Core SDKs can be installed Side-by-Side, we can still target any of the versions that we have installed.

There is a known issue with the first run of version 1.0 of the SDK after installing the 2.0 preview, but it’s covered pretty well on the .NET Core 2.0 preview known issues page.

Because .NET Core supports Side-by-Side development, we can still use the application templates for the different framework versions. For example, if we run the following command:

dotnet new console --framework netcoreapp1.1

the .NET Core SDK will produce a console application which targets netcoreapp 1.1 (.NET Core 1.0.4). But if we issue the following command:

dotnet new console --framework netcoreapp2.0

the .NET Core SDK will product a console application which targets netcoreapp 2.0 (.NET Core 2.0 preview).

It’s also worth noting, that the following command (after having installed the .NET Core 2.0 preview):

dotnet new console

will also produce a console application which targets netcoreapp 2.0

The Global global.json

To ensure that specific versions of the .NET Core SDK are used for all new projects, a global.json file can be placed in a user profile directory

or anywhere with a directory tree, as we’ll see in a moment

and the SDK will only produce new projects based on the version of the SDK specified in the file.

When .NET Core SDK 2.0 preview 1 is installed, performing the following command:

dotnet --version

which returns the version number, will return something similar to the following:

2.0.0-preview1-005977

However, if the following global.json file is created and stored in the user profile directory:

{
"projects": ["src", "test" ],
"sdk": {
"version": "1.0.3"
}
}

and the same command is run:

dotnet --version

the following should be output to the terminal:

1.0.3

This can be extremely useful when committed to source control, as it will ensure that the correct version of the .NET Core SDK is used at compile time. Which is probably why it’s a convention for .NET Core development.

As with previous versions of .NET Core, you can leverage this to have sub-directories which target different versions of the SDK.

global.json Example
This image is a little confusing, I agree. But bear with me

In the above image, I’ve added a selection of different global.json files to different sub-directories. In real life, you would name them all “global.json”, I’ve added version numbers to the names to help show what I’m about talk about.

If we start at the root of the above directory tree and issue the ‘dotnet –version’ command, we should receive the following output:

2.0.0-preview1-005977

This is because there isn’t a global.json in this directory (or any other directories above it), also it is assuming that we have .NET Core SDK 2.0 preview 1 installed

But if we change directory into ‘top-level-directory’ and run the same command, we should receive the following output:

1.0.3

This is because there is a global.json file inside the ‘top-level-directory’ with the following contents:

{
"projects": ["src", "test" ],
"sdk": {
"version": "1.0.3"
}
}

If we change directory into ‘2.0.0-sub-directory’ and run the ‘dotnet –version’ again, we’ll received the following output:

2.0.0-preview1-005977

This is because there is a global.json file inside the ‘top-level-directory’ with the following contents:

{
"projects": ["src", "test" ],
"sdk": {
"version": "2.0.0"
}
}

First Boot Speed

A lot of work has gone into increasing the speed of the first boot of ASP.NET Core 2.0 applications.

There was an absolutely amazing moment during Scott Hanselman and Dan Roth’s talk (“Introducing ASP.NET Core 2.0“), where Dan Roth showed off the cold boot times of an ASP.NET Core 1.1 and 2.0 application.

ASPNETCore 1.0 start up time va ASPNET Core 2.0 start up time
I left the timestamp on the screen shot so that you could jump to that section, in case you don’t believe me

As you can see from the image above, the cold boot time for an ASP.NET Core 1.1 application bounced between 7.243 and 3.643 seconds. And the ASP.NET Core 2.0 application’s cold boot time was between 0.984 and 0.784 seconds.

How did we do this?

We’ve done a couple of things. We have a Runtime store now that ships with .NET Core that includes all of ASP.NET Core in it.

That Runtime Store has already been cross gen (compiled into native code).

Then on publish we enabled view pre-compilation by default. So all the views in the app have been pre-compiled into the assembly. They don’t have to be compiled on the fiy, which of course takes a bunch of time on start up.

Dan Roth – https://channel9.msdn.com/Events/Build/2017/B8048

Since the Runtime Store contains all of the ASP.NET Core code, and it has already been compiled down to native code (and does not need to be JIT compiled from IL to native code), this takes less time to boot and run.

Conclusion

There are a lot of exciting things coming out of Build this year, and I’ll be covering even more things next week. We have a new version of the .NET Core SDK, a new version of the .NET Standard, and a more simplified and streamlined way to include ASP.NET Core namespaces.

All of that, and our application builds are now smaller and faster to boot.

Related Posts

A .NET developer specialising in ASP.NET MVC websites and services, with a background in WinForms and Games Development. When not programming using .NET, he is either learning about .NET Core (and usually building something cross platform with it), speaking Japanese to anyone who'll listen, learning about languages, writing for his non-dev blog, or writing for a blog about video games (which he runs with his brother)