Scotty H
Scotty H

Reputation: 6714

C# grandchild project DLLs not included in msbuild package

I have a C# project X that references a C# project Y that references a C# project Z. So the dependency chain looks like this: X => Y => Z. There is no direct/explicit dependency X => Z. When I build a package for publication using msbuild command

msbuild DesignService.csproj /m /p:Configuration="Debug" /p:Platform="AnyCPU" /verbosity:quiet /t:Package /p:PackageLocation=X.zip /p:PackageAsSingleFile=True

I get a zip file that has DLLs for X and Y, but not Z. Then when the package is published (to an Azure App Service) I get runtime errors when a call is made to code in Z, saying the DLL can not be found. If I add Z as a direct/explicit reference in X, it works just fine. But I don't think I should have to do this.

How can I get DLLs for Z in my publish package from msbuild without adding an explicit reference in X?

Upvotes: 16

Views: 620

Answers (2)

ThePretendProgrammer
ThePretendProgrammer

Reputation: 1517

There is no straightforward way to do this, even though this issue has been raised multiple times with msbuild. In terms of workarounds, the most popular ones are to make some use of the 'Z' project assembly (create a dummy instance of some class from the 'Z' project in the 'X' project) or to add a direct reference in the 'X' project to the 'Z' project.

The most clean workaround in my opinion is explained in this blog. Essentially, it involves creating a separate .targets file, which is nothing but instructions for msbuild to ensure that while it builds and packages the DLLs, it also includes all transitive dependencies. This .targets file then needs to be added to your X.csproj file so that on building it using msbuild, this targets file gets invoked.

Upvotes: 1

Joey Cai
Joey Cai

Reputation: 20097

Why does this happen

X.csproj was invoked, and because it has a project reference to Y.csproj, it invokes Y.csproj — it “goes around the back”. Z.csproj hasn’t necessarily built yet, so the build breaks.

How to fix

Follow this principle: do not use dependencies expressed in the solution file at all.

You could put a project reference in the project instead. It would look like this – note the metadata element, and all this is inside an <ItemGroup> tag of course:

<ProjectReference Include=”… foo.csproj”> 
    <ReferenceOutputAssembly>false</ReferenceOutputAssembly> 
</ProjectReference>

Although it’s tiresome to have to edit your projects in this way to make the bug go away, it’s a best practice to use project references instead and consider the solution file merely a “view”.

You’ll end up with projects that if you want can be built without a solution file.

For more details about how to fix the problem, you could refer to this blog.

Upvotes: 1

Related Questions