blog post image
Andrew Lock avatar

Andrew Lock

~5 min read

The Microsoft.AspNetCore.All metapackage is huge, and that's awesome, thanks to the .NET Core runtime store

In the ASP.NET Core 2.0 preview 1 release, Microsoft have released a new metapackage called Microsoft.AspNetCore.All. This package consists of every single package shipped by Microsoft as part of ASP.NET Core 2.0, including all the Razor packages, MVC packages, Entity Framework Core packages, everything!

Now, if you're first reaction to this news is anything like mine, you're quite possibly cradling your head in your hands, thinking they've completely thrown in the towel in creating a small, modular framework. But don't worry, there's more to it than that, and it should help deal with a number of problems.

Note, the Microsoft.AspNetCore.All metapackage will only ever target netcoreapp2.0, as it relies on features of .NET Core as you'll see. If you are targeting .NET Framework, then you will still be able to use the individual ASP.NET Core packages (as they will target netstandard2.0, it is just the metapackage that will not be available.

Version issues

From the outset, ASP.NET Core has been plagued by confusion around versioning. First of all, you have the confusion between the .NET Core runtime version and the .NET tools version (I discussed those in a previous post/). On top of that, you have the somewhat abstract version of ASP.NET Core itself, such as ASP.NET Core 1.0 or 1.1.

And then you have the package versions themselves. Every package in ASP.NET Core revs its version number semi-independently. This makes sense semantically - if a package doesn't change between two versions of ASP.NET Core, then the version numbers shouldn't change.

Unfortunately this can make it tricky to work out which version of a package to install. For example, version 1.0.5 of the Microsoft.AspNetCore metapackage (that I talk about here/) adds the following packages to your application:

"Microsoft.AspNetCore.Diagnostics" (>= 1.0.3)
"Microsoft.AspNetCore.Hosting" (>= 1.0.3)
"Microsoft.AspNetCore.Routing" (>= 1.0.4)
"Microsoft.AspNetCore.Server.IISIntegration" (>= 1.0.3)
"Microsoft.AspNetCore.Server.Kestrel" (>= 1.0.4)
"Microsoft.Extensions.Configuration.EnvironmentVariables" (>= 1.0.2)
"Microsoft.Extensions.Configuration.FileExtensions" (>= 1.0.2)
"Microsoft.Extensions.Configuration.Json" (>= 1.0.2)
"Microsoft.Extensions.Logging" (>= 1.0.2)
"Microsoft.Extensions.Logging.Console" (>= 1.0.2)
"Microsoft.Extensions.Options.ConfigurationExtensions" (>= 1.0.2)

As you can see, the version numbers are all over the place - it's basically impossible to know which version to install without polling NuGet to find the latest version of each package. And updating your packages becomes a nightmare, especially if you're working outside of VS or Rider, and are manually editing your .csproj files.

With ASP.NET Core 2.0, Microsoft are moving to a different approach. While strict semantic versioning and many small packages is a great idea, the realities of that sure get confusing, especially when you have a large project.

The Microsoft.AspNetCore.All metapacakge references all of the ASP.NET Core packages, but it does so with a single version number:

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

Updating your ASP.NET Core packages will just involve updating this one package. No more trying to work out which packages have changed and which haven't.

"But wait", I hear you cry, "if that metapackage includes every package in ASP.NET Core, won't that make my published application huge?". Actually, no, thanks to a new feature in .NET Core 2.0.

Number of packages

.NET Core 2.0 brings a new feature called the Runtime Store. This essentially lets you pre-install packages on a machine, in a central location, so you don't have to include them in the publish output of your individual apps.

You can think of the Runtime Store as a Global Assembly Cache (GAC) for .NET Core. As well serving as a central location for packages, it can also ngen the libraries so they don't have to be jit-ed by your application, which improves startup times for your app.

When you install the .NET Core 2.0 preview 1, it will also install all of the ASP.NET Core packages into the runtime store. That means they're always going to be on a machine that has the .NET Core 2.0 runtime installed. If you've installed the preview of .NET Core 2.0 preview 1, you can find the store here: C:\Program Files\dotnet\store.

The runtime store

Surprise, surprise, this setup works brilliantly with the Microsoft.AspNetCore.All metapackage!

When you publish an ASP.NET Core 2.0 app that references the Microsoft.AspNetCore.All you'll find that your publish folder is miraculously free of the ASP.NET Core packages like Microsoft.AspNetCore.Hosting and Microsoft.Extensions.Logging.

Just compare the output of the basic dotnet new mvc template in an ASP.NET Core 1.0 app to the 2.0 preview 1. Look at the size of that scrollbar in the top image - 94 items vs 13 items in ASP.NET Core 2.0.

Comparing ASP.NET Core 1.0 vs 2.0

Making the publish size smaller has a number of obvious benefits, but one of the biggest in my mind is making the size of your Docker images smaller. Docker works in layers; when you deploy your app with docker, whole of ASP.NET Core will now be included in the base image, instead of as part of your app. Shipping updates to your app only requires shipping the files in your publish folder; a smaller publish folder means a smaller Docker image file, and a smaller image file means a faster deployment! Win win.

Discoverability of APIs

The final advantage of the Microsoft.AspNetCore.All package is a massive boon to new developers - discoverability of the APIs available. One of the problems with having many small packages in ASP.NET Core 1.x, is that you won't necessarily know what's available to you, or which package an API lives in unless you go checking the docs or browsing on NuGet.

Now, granted, VS 2017 has got much better at this, as you can turn on suggestions for common NuGet packages, but you still have to know what APIs are available to you:

NuGet suggestions

If you're working in VS Code, or you don't already know the APIs you're after, this is no use to you.

In ASP.NET Core 2.0, that problem goes away. Your project already references all the packages, so the APIs, and IntelliSense suggestions, are already there!

VS  Code suggestions

In my mind, this is a massive help for new users. I still find myself trying to remember the exact API I'm looking for to prompt VS to install the associated package, and this problem is just completely solved!

Summary

The Microsoft.AspNetCore.All metapackage includes every package released by Microsoft as part of ASP.NET Core. This has a number of benefits:

  • It reduces the package version management burden
  • It reduces the number of packages that need to be published with the app
  • It makes it easy to use the core packages without having to add them to the solution explicitly

These benefits should make writing ASP.NET Core 2.0 apps against .NET Core just that little bit easier, so kudos to all those involved.

Andrew Lock | .Net Escapades
Want an email when
there's new posts?