Skip to content

Microsoft.XmlSerializer.Generator adds DotNetCliToolReference to project #69435

Description

@zivkan

Description

NuGet is designed to be deterministic, meaning every restore should, in theory, work the same. Therefore, on command line restores, NuGet tells MSBuild to ignore props and targets files from packages, so they can't modify the restore graph. However, in Visual Studio, NuGet does not interact with MSBuild directly, VS is designed for project systems to interact with MSBuild, and other components use APIs on the project system instead. The project system does not honor NuGet's deterministic quality.

The Microsoft.XmlSerializer.Generator package tries to add a <DotNetCliToolReference item to the project in its props file:

&lt;DotNetCliToolReference Include="$(PackageId)" Version="$(PackageVersion)" /&gt;

As described above, this will not work from command line restores. But in Visual Studio, if you git clean, on solution load NuGet will see a PackageReference to this package, and restore it, but since the package's props file is not yet available, the DotNetCliToolReference is not added, just like on the command line. After the VS project system then re-evaluates the project, to see what changes the packages make (needed for things like Source Link, Git Versioning, etc), it will see that there's a new DotNetCliToolReference that was not there before, and tell NuGet to do a second restore. In this second restore NuGet will include the package as both a package reference and a DotNetCliToolReference.

Note, the docs for the package explicitly tell customers to add both a PackageReference and DotNetCliToolReference reference: https://docs.microsoft.com/en-us/dotnet/core/additional-tools/xml-serializer-generator

If the package's props file did not try to add the DotNetCliToolReference itself, then customers would more quickly learn that they're not using the package as intended, rather than being confused about why it works in VS but not on the command line. In fact, the props or targets file could check if the DotNetCliToolReference is missing, and give customers a clear error message, rather than the obscure error that currently happens on the command line.

Reproduction Steps

Create a project that uses/needs Microsoft.XmlSerializer.Generator, and delete the obj/ folder in between tests.

Expected behavior

Project works the same in Visual Studio and on the command line (think CI build server)

Actual behavior

Customer is reporting that they get an error message: https://discord.com/channels/732297728826277939/734779766137421894/975976174117322783

Version for package Microsoft.XmlSerializer.Generator cannot be resolved

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

Feel free to reach out to me, or others in the NuGet team if you want to discuss any of this. It's been a long, long time since we (NuGet team) talked to the project system team about this, so I planning on bringing up this topic, to see if we can find a way to make VS work the same way as CLI restores (ignore package props/targets files), which will have the unfortunate consequence of breaking this package in VS, but will have the benefit of no longer giving package authors a false impression that their package works, when they only test in VS.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions