msbuild: MSBuild does not honor solution Project Dependencies

Issue Description

There does not appear to be a functional way to represent a soft (build order only) project dependency using the MSBuild command line. Visual Studio has a feature to indicate that one project depends on another without referencing it, which works, but when building from the command line these relationships are not honored.

Steps to Reproduce

In one scenario we need this functionality, we have a basic pattern with at least 3 projects (this is slightly simplified from our real world implementation, but expresses the important moving parts):

  • A Contracts project that contains serializable POCO DTO types and service interfaces.
  • A Web API project with controllers that implement service interfaces and return the DTOs.
  • A Client project that contains generated typed HTTP clients (which also implement the service interfaces so that shared code can swap implementations between server-side and client-side)

The Contracts project is a fairly straightforward class library that targets netstandard2.0.

The Web API project is an ASP.NET Core project (currently targeting netcore3.1, but with some prototypes migrating to net6 that have the same issues) that references the Contracts project. There is a post-build target that generates an Open API Specification file describing the controllers (NSwag json output).

The Client project is a class library that targets netstandard2.0 and references the Contracts project. There is a pre-build step that uses NSwag to generate typed HTTP clients (and some supporting extension methods for registering them in a service collection, etc.). This project has a loose build order dependency on the Web API project (because it consumes the swagger json file produced post-build in the Web API, but it can not–and does not want to–reference the netcoreapp3.1 project from the netstandard2.0 project).

Expected Behavior

In Visual Studio we use the “Project Dependencies” dialog to indicate that Client depends on Web API and it works well within the IDE. Ideally that feature would just work when building from the command line as well.

Actual Behavior

When a clean source tree is checked out or the bin/obj directories are cleaned out (or, really, when the swagger json file does not exist on disk) the build fails because the Client project builds before the Web API project is finished.

Analysis

We’ve tried a variety of ways to work around this with a ProjectReference from the Client project to the Web API project, but can’t seem to figure out the right metadata/configuration to express the loose dependency. Any guidance would be greatly appreciated. Here are some of the things we’ve tried in a variety of combinations:

<ProjectReference Include="..\AspNetCore.TestHarness\AspNetCore.TestHarness.csproj">
  <Private>false</Private>
  <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
  <ExcludeAssets>all</ExcludeAssets>
  <PrivateAssets>all</PrivateAssets>
  <DisableTransitiveProjectReferences>true</DisableTransitiveProjectReferences>
  <DisableTransitiveFrameworkReferences>true</DisableTransitiveFrameworkReferences>
  <SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>
</ProjectReference>

Some references found along the way:

Versions & Configurations

This has been an ongoing struggle with VS 2017, 2019, and 2022 in a variety of different scenarios. One of the latest machines I reproduced this on is running:

MSBuild version 17.3.1+2badb37d1 for .NET Framework 17.3.1.41501

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 22 (9 by maintainers)

Commits related to this issue

Most upvoted comments

The same mechanism applies to the solution ordering, when MSBuild applies it. When VS applies it it works differently.

So I think it’s worth trying the change in your existing codebase.

I was trying to create a minimal repro together in spare time but got sidetracked by a production issue as soon as I got back from holiday so apologies on the delay for additional information. In the meantime our build server has started failing in a way that is blocking development/testing so I’m going to get some binlogs together ASAP because this has become a high priority blocker for us in the time since we last spoke, and then I’ll get back to trying to get the repro together (which I’m mildly concerned may be difficult to isolate in a standalone solution).

Yes! Open a feedback ticket, which offers uploads confidential to Microsoft.

After it’s created, that will open an internal bug. If you post the link here we can short-circuit the normal “find the right team for this” process.

@Forgind yeah, we started with that (and it’s in the sample attempt at a workaround above) but there were still side effects from transitive dependencies so we’ve been trying to add more metadata to varying (unsuccessful) results.