With the latest SDK, the version of Microsoft.NetCore.App in your project file is not longer being honored.
The M.NC.App is being inferred by the SDK and the user choice is being completely ignored.
I know we can set DisableImplicitFrameworkReferences, but I am not sure that telling our customers to learn these nobs is the right thing to do.
Whatever the user sets should win.
Besides, this will create other problems:
@srivatsn @nguerrera @dsplaisted can you please look at this right away? This seems like a big UX impact for the upcoming release.
@eerhardt @blackdwarf @mlorbetske FYI as this will likely impact work you're doing right now. What we saw was that all CLI projects were reverted to NetCoreApp 1.0.1 despite specifying 1.0.3 in our project files.
Are you are writing <PackageReference Update="Microsoft.NetCore.App" Version="1.0.3" /> in your csproj? The item is added by the props with an include and to update the metadata, you have to use the Update syntax.
I suspect you are using the Include syntax? If so, @dsplaisted mentioned that two items will be created and NuGet might be picking the higher version or, more likely, the first one. If you folks are running into this, then this is likely going to be a very common mistake.
All of the bullets mentioned above are goals though and are possible as long as you use the Update syntax and I believe VS tooling will use the Update syntax correctly when upgrading the package. @dsplaisted @rainersigwald @AndyGerlicher @cdmihai - any suggestions on how to prefer the item in the project file if it was created using the Include syntax?
See #450 for context on this.
You can override the version of the package with the following:
<PackageReference Update="Microsoft.NETCore.App" Version="1.0.3" />
For NETStandard.Library, you can use the Package Manager UI to update the version of the package and it will write this to your project file. The reference to Microsoft.NETCore.App is marked as ReadOnly to prevent updates from showing up, because things can break if the version of Microsoft.NETCore.App that you reference doesn't match the target framework version of your project. If we change the package so that you can use the latest version of the package with earlier TFMs, then we will probably remove the ReadOnly setting for that reference.
You can also modify the version of the shared framework that is written to runtimeconfig.json by specifying the RuntimeFrameworkVersion property:
<RuntimeFrameworkVersion>1.0.3</RuntimeFrameworkVersion>
If this property is defined, then it's value will be used as the version of the shared framework written to runtimeconfig.json. Setting the property won't change which version of the Microsoft.NETCore.App package is referenced and hence compiled against, but I believe there shouldn't be any API changes between the patch versions so that shouldn't matter.
If we knew NuGet's preference perhaps the code could be changed to ensure that NuGet prefers the user's choice? Ideally, the default would be set in our .props, then the user's choice would override our default, and then NuGet would prefer the user's choice. @rrelyea @rohit21agrawal is that feasible? Alternatively, could we add the implicit reference in the .targets file so it gets added after the user's choice?
If we added in the targets, then you can't use the Update syntax to update. Two items is not a good place to be because then every consumer needs to know which one to pick.
Two items is the state we were in, right? I think that avoiding the update syntax should be an explicit goal. Folks shouldn't have to think about which one to use for a give Package Reference. Neither is always right and there is no project file artifact that tells us which to use in a given context. The rule seems to be "go figure out if an SDK is adding this reference" which is pretty bad...
Currently going through the templates updating them to make use of the implicit references. The packageref for libraries going away is nice, but every app has an update to 1.0.3 which defeats the purpose imho. Moreover, users would no longer have a recognizable place to update should they want to move to a newer version (or pin to a specific one & survive behavior changes with default version updates) if we go ahead with making this entirely implicit.
Folks shouldn't have to think about which one to use for a give Package Reference.
The idea behind the implicit references is that folks should generally not need to think about Package References to NETStandard.Library or Microsoft.NETCore.App at all. As much as possible, they should be an implementation detail that's not surfaced to users.
but every app has an update to 1.0.3
We should instead just update the SDK to implicitly reference 1.0.3 if you're targeting netcoreapp1.0. We have #572 filed for this.
Sorry, must have missed #572 in my notifications previously, thanks for moving it up to 1.0.3 by default - when do we expect that to be ready?
I agree with the sentiment that users shouldn't have to worry about it, but I do still worry about the discovery issues for non-VS development environments and (with the current lack of version assertions in projects for particular SDKs) the possibility of having different implicit package references in different contexts.
Since we float to the latest patch automagically, you don't actually need to update to 1.0.3 to target it. Once you install it, it will be used. That even happens today if you target 1.0.1 but install 1.0.3.
Yep, I agree that this should not often be surfaced to users. When it's needed, we would best serve our customers if they didn't need to deal with an unexpected pattern. I'm really worried about users that need to specify the framework version. This Update syntax is only going to be used for PackageReferences in this scenario, AFAIK. People will be very familiar with PackageReferences and will quite naturally use Include instead.
If we feel that we cannot make Include work, can we at least fail with a good error message when Include is used? Something that enables easy searches and, ideally, tells folks what to do?
@davidfowl you mean for binding portable apps at runtime? Or are there associated changes for design-time and standalone apps as well?
Portable applications. Shared frameworks need to use packages to get the implementation until we fix how that works (getting implementations from the shared framework always). We need to think about standalone more here.
@piotrpMSFT
I'm really worried about users that need to specify the framework version.
Can we just tell people to use the RuntimeFrameworkVersion property in that case instead of changing the package version?
@dsplaisted also, will there be explicit support added for automatically picking the 1.1.0 packageref (looks like it's just a 1.0 thing currently)?
@mlorbetske The default right now is to reference the same version of the Microsoft.NETCore.App package as the version from the TargetFramework. So if your TargetFramework is netcoreapp1.1, you'll get version 1.1.0 of the package. The line you linked to is the exception to that to reference a later patch version when targeting netcoreapp1.0.
@dsplaisted got it - the linked bit is a special case for 1.0 as it doesn't go to 1.0.0. Not sure why that wasn't clear given that the general case is on the line above.
Web templates for VS & all the templates in the PR for the new "new" in CLI (currently going through the build process, the PR will be updated with the new package version numbers in the morning) have been updated to not include references to Microsoft.NETCore.App or NETStandard.Library
This problem also exists when adding a reference to Microsoft.AspNetCore.Mvc.Core version 1.1.0 which requires NETStandard.Library 1.6.1. dotnet restore complains about a downgrade even though I didn't specify NETStandard.Library 1.6.0 in my csproj. This is not the behaviour I would've expected.
More data on this:
This makes cross-targeting really messy. +1 for suggestion above that we shouldn't require the 'Update' syntax. Not only counterintuitive and nondiscoverable, it makes code quirky.
For example, in the latest SDK (1.0.0-preview5-004468), the only way to get dotnet-restore + dotnet-pack to find the right NETStandard.Library version is:
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<PropertyGroup>
<TargetFrameworks>net451;netstandard1.3</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)'=='net451'">
<PackageReference Include="NETStandard.Library" Version="1.6.2-*"/>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='netstandard1.3'">
<PackageReference Update="NETStandard.Library" Version="1.6.2-*"/>
</ItemGroup>
</Project>
If you don't vary the right Include/Update syntax per TFM, you end up with this situation: https://github.com/dotnet/sdk/issues/614
@natemcmaster what is the reason here to target netstandard.library for full framework if I may ask? It currently causes headaches for consuming projects like https://github.com/dotnet/corefx/issues/14705#issuecomment-269058492
what is the reason here to target netstandard.library for full framework...?
@dasMulli see https://github.com/dotnet/corefx/issues/12053
Adding Blocking Partner label because we can't proceed with ASP.NET Core due to this.
@Eilon How is this blocking ASP.NET Core?
Almost all of ASP.NET Core packages target NETStandard.Library 1.6.2-*. Without adding workarounds to our csproj, our packages get packed with 1.6.0 instead of 1.6.2.
Side note:
I've seen quite a few ppl both on slack and GH issues trying to update from 1.0.* to 1.1.0 by just hitting "update all" in NuGet and not changing the target framework.. This of course breaks but shows that it's better to have a single place where the version comes from than having to educate everyone about why a NuGet and the target framework have to be updated. In my opinion, updating the target framework is better because it is a different kind of modification than just updating packages (e.g. going from netcoreapp1.0 to netcoreapp1.1. maybe also from netstandard1.6 to netstandard1.7/2.0?).
And for custom configurations, you can still have shared props/targets files to import..
Just to understand the ASP.NET Core issue, if the package reference wasn't implicit, then you'd have to update the version of the package in all of your csproj's, right? I'm trying to understand if the issue is that you have to touch all of your project files, or if the change you have to make to them is too verbose/ugly, or what.
Seems like there are a few issues we need to react to from this change.
PS @natemcmaster wow, that's really nasty.
@davidfowl yes, the impact this is having is non-trivial for both libs and apps. We need to consider this all-up.
Re: https://github.com/dotnet/sdk/issues/596#issuecomment-271466250
Part of the issue is that we'll need to touch all of our project files to move from RC.2 to RC.3. If that were the only issue, this would a manageable, though cumbersome, requirement.
The bigger concern we want addressed is that cross-targeting requires this ugliness in the project https://github.com/dotnet/sdk/issues/596#issuecomment-271438520 or opting out via the DisableImplicitFrameworkReferences property. Both require a high-level knowledge of SDK internals, far beyond what I would expect from the average user.
Plus, I'd echo the concerns @livarcocc mentioned in the original issue about LTS/FTS and complications down the road caused by hardcoding versions into the SDK now.
Part of the issue is that we'll need to touch all of our project files to move from RC.2 to RC.3
@natemcmaster Sounds like lineup files would be adequate here, right? https://github.com/Microsoft/msbuild/issues/1493
@cdmihai not sure. I'd have to see more details on how lineup files will be implemented.
cc @DamianEdwards @davidfowl - I think this is relevant to the mtg you have later today?
We've decided to revert the implicit packageref feature until we can make it work fully E2E. Using this issue to track the revert.
This is now fixed.
Most helpful comment
Two items is the state we were in, right? I think that avoiding the
updatesyntax should be an explicit goal. Folks shouldn't have to think about which one to use for a give Package Reference. Neither is always right and there is no project file artifact that tells us which to use in a given context. The rule seems to be "go figure out if an SDK is adding this reference" which is pretty bad...