Skip to content

Instantly share code, notes, and snippets.

@MarneeDear
Created March 19, 2020 21:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MarneeDear/f558df06d1811fcfb042491bedb3d816 to your computer and use it in GitHub Desktop.
Save MarneeDear/f558df06d1811fcfb042491bedb3d816 to your computer and use it in GitHub Desktop.
Understanding AspNetCore 3.0 vs AspNetCore 2.x

afaik, almost all of Microsofr.AspNetCore.* assemblies will live within Microsoft.NET.Sdk.Web, unfortunately the Microsoft.Extensions.* packages still live as separate nuget.

that's normal
Msft.Extensions.* were always separated from Msft.AspNetCore.* because they are "USED" by AspNetCore but are not part of it : DependencyInjection / Logging / Configurations / Options are good examples.
See how they are targeting netstandard2.0 you can use it in your old stack like Owin / Xamarin ... (kinda great for Logging / Options)

I'm still seeing app the Microsoft.AspNetCore packages on nuget are 2.2

DONT FORGET that the new Microsoft.AspNetCore.... 3.0 is a runtime that "inherits" of the netcoreapp3.0. This means two things :

  • it can't run anymore on net4xx (no more netfx 💛)
  • you need to actually target netcoreapp3.0

As @poke explained :
the NuGet packages are on nuget.org are the packages that target netstandard, and as such they are limited to 2.2 and below. 2.1 is LTS and will be supported longer on .NET Framework, so those packages will continue to be very valuable there.

The thing is that now Microsoft.AspNetCore.App is a FrameworkReference and not a PackageReference anymore
2.2 has this big ambiguity (ended up being an issue) where the Microsoft.AspNetCore.App package was reference as a PackageReference but should never had a Version specified (it was supposed to be pull from the Sdk being used at build time global.json)
If you messed up dependencies, it could in some scenario, take the resolved weird version from nuget.org instead of the ones from the sdk

the FrameworkReference attempt to fix it, IT HAS TO BE installed at build time.
For that to work you just install the Sdk (nothing special in fact ^^). That's how it know what sdk to look for the <FrameworkRerence Include="Microsoft.AspNetCore.App" />
EDIT : i previously said you had to change the SDK to the Web one, pretty sure it's a mistake ... and you should not need that :

  • For example, imagine creating a WPF application (it uses the Desktop SDK), if you need some AspNetCore Assemblies, then you can't have both <Project Sdk="...."> at the same time.
  • When you create a dotnet new webapi, it does have the Web SDK, and you see no <FrameworkRerence Include="Microsoft.AspNetCore.App" />, it will be included by the SDK itself "for free"

If you are developping a library :

  • try to target netstandard2.0
  • if you need special new api from netstandard2.1, well just update to <TargetFramwork>netstandard2.1</TargetFramwork>
  • if you are doing a lib that depends on aspnetcore3, then target netcoreapp3.0 (instead of netstandard2.x) and add a <FrameworkReference Include="Microsoft.AspNetCore.App" />
  • The same idea applies for Wpf/Winform/Uwp for FrameworkReference
  • The trick is when you are doing a lib that need to support BOTH aspnetcore2.x + 3.x :
<PropertyGroup>
  <!-- in order to consume the aspnetcore3 metapackage you need to also target netcoreapp3.0 here -->
  <TargetFrameworks>netstandard2.0;netcoreapp3.0</TargetFrameworks>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
  <!-- every single aspnetcore 2.x one by one -->
  <!-- don't even try meta package (the .App) in 2.x in lib -->
  <!-- you need to align version here -->
  <PackageReference Include="Microsoft.AspNetCore.Http.Abstraction" Version="2.2.6" />
  <PackageReference Include="Microsoft.AspNetCore.Foo" Version="2.2.6" />
  <PackageReference Include="Microsoft.AspNetCore.Bar" Version="2.2.6" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
  <!-- only one ref / note that it's a meta package -->
  <!-- no version -->
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

<ItemGroup>
 <!-- all dependencies that are not TFM specific -->
</ItemGroup>
* where : only while using .NetCore
* why : because before(NetFx / .net full framework), Both runtime (coreclr) and BCL (CoreFx) were tied together
so in order to get `HttpClient` being the same everywhere you had to either
- install the same version/patch of NetFx
- use binding redirect and hope it goes well
This type of reference (GAC references) are tied to windows / Registry / magic folder / illusion of SxS (side by side > same assembly multiple version installed,.... or not)
When .NetCore appeared it was design with goals
* one of them is being XPlat so no more thing like GAC ....
* one was to split bcl(dotnet/CoreFx) out of runtime (dotnet/coreclr) so that it’s way faster to release change to the BCL
eg: like changing sync api to async api in httpclient/sql/file system, which MIGHT (or not) be independent from runtime
With that in mind ... they needed to find a way to ship it ... luckily nuget was here for that so CoreFx repo was splitter in hundreds of little indépendant package (nuget)
This down side of doing this is that the développer experience had a big beat down ...
Since the BCL was splitter down to hundred of package, you need to pull down manually every single nuget you needed to work
It was “magic” during NetFx because as said ... it was part of the framework so already “present”
So in order to help developers, someone came up with a brilliant idea ... why not decide what’s very used and group them ?
That was the beginning of metapackage
Creating an “empty shell” referencing the small ones so that Intellisense kicks in and no need of `dotnet add package` every time you need to expand your needs
These metapackage had few draw back and what I’m gonna write might be incorrect :
There’s multiple meta package
* only NetCore app (slim layer)
* aspnetcore.App (aspnetcore slim layer)
* aspnetcore.All (aspnetcore.app + ef + identity) <== not sure if this one is considered as a meta package, I believe so
These metapackage are installed with the installation of the SDK (they are in a sub folder of the sdk)
BUT they were also shipped through nuget (at least for 2.x)
So when you created an app in 2.x you had a
`<Project Sdk=“.....Sdk”` or ` Web.Sdk` but you also had
`<PackgeReference Include=“Microsoft.AspNetCore.App” />` <== no version on purpose ... it’s supposed to be driven by the installed SDK
this is where the fun begin
Is you do add a version that does not match the SDK => the meta package will be pulled from nuget.org
(Not pre-jitted for first) but also very fun to understand why version does not match global.json
So to address that, 3.0 introduced something new `FrameworkReference`, they are also installed with the SDK (not sure how to create and install custom one)
They are automatically reference by the sdk
=>
`project sdk=“....web.sdk”` will reference for you the frameworkreference yo `Msft.anc.app`
Now if the still is the slim `NetCoreapp.sdk` and you need thing part of a specific framework ... you leave the sdk alone but you explicitly add this to your csproj :
`<FrameworkReference Include=“Microsoft.AspNetCore.App” />`
(The same exists for desktop winform and uwp)
Also to be sure there’s no weird quirk with the versions
Packages that are inside these framework reference won’t be released as nuget (so that it’s SDK Driven and consistent with the dev experience)
Why would you do that ?
Well as a library author, if you create a nuget for aspnetcore you need to access these types but you still want the slim sdk (you do not want for example all the tagert/publish stuff specific to deploying website)
Since there are no nuget anymore, you just reference the framework
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment