PackageReference to project in the same Solution/git repository - c#

At the moment I'm trying to setup a solution with a implementations class library and an abstractions project. I want to have both packages on nuget.org.
Normally when you're just using ProjectReferences, you'd only have to point to the csproj:
Random.Abstractions:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Description>Abstractions for the Randomizer</Description>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<Company>MyCompany</Company>
<Authors>Pieterjan De Clippel</Authors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" />
</ItemGroup>
</Project>
Random
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Random.Abstractions\Random.Abstractions.csproj" />
</ItemGroup>
</Project>
But off course when you build a nuget package, you don't want the Random.Abstractions.dll to be inside the Random nuget package, but the Random package to depend on the Random.Abstractions package. But since this package doesn't exist yet, you can't build it yet.
Microsoft is able to solve this problem like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
...
</PropertyGroup>
<ItemGroup>
...
</ItemGroup>
<ItemGroup>
...
<Reference Include="Microsoft.AspNetCore.DataProtection.Abstractions" />
</ItemGroup>
</Project>
So this is neither a ProjectReference nor a PackageReference, which is why they are able to:
build and test the solution locally (so there they'd be acting as ProjectReferences)
push the code to GitHub and let the GitHub Actions create and publish the new version of the packages, while they depend on each other (so there they'd be acting as PackageReferences)
I've tried doing the same in my solution, but the project containing the concrete implementations is unable to find the abstractions project:
MyCompany.Random.Abstractions.csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Description>Abstractions for the Randomizer</Description>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<Company>MyCompany</Company>
<Authors>John Wick</Authors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" />
</ItemGroup>
</Project>
MyCompany.Random.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Reference Include="MyCompany.Random.Abstractions" />
</ItemGroup>
</Project>
So no ProjectReference (we don't want the dll to be in this nuget package), no PackageReference (the package is not yet published), but just Reference.
But somehow I'm still getting an error that the Abstractions assembly cannot be found:
I've checked the NuGet.config but there's nothing really special in there.
How can I use the Reference tag in a dotnet-based project, in order to reference to code while building/testing locally and reference the new package while building/pushing in a CI pipeline?
Reference to Microsoft.NET.Sdk documentation
Update:
#pinkfloydx33, you're right. I can see only one assembly/dll inside the nupkg:
Update 2:
I added the Microsoft.SourceLink.GitHub package to my project, and after downloading/unzipping the new version of my package I can see the following nuspec:
Where 77b181a24a83e46b4c80376f65bb305bedba1a64 is the commit ID.
Thanks for the tip.

Related

Project reference in Nuget

I need to create a Nuget of project A which is dependent on project B (not a nuget project, local one).
I have added Project B as project dependency to project A and enabled property to generate package on build. It is creating nuget package file but not including all the files from project A.
I tried few things and google also but not finding much help.
I found one similar question Build NuGet Package automatically including referenced dependencies
but not working. I am able to create pkg but with few files copied over. while I can see all the files in debug folder. No idea on what basis Nuget is picking few files from project A.
Can anyone tell me what's wrong here.
<Project Sdk="Microsoft.NET.Sdk" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<TargetFramework>net462</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageVersion>1.0.0.0-alpha</PackageVersion>
<Platforms>x64</Platforms>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<PlatformTarget>x64</PlatformTarget>
<NoWarn></NoWarn>
<WarningsAsErrors />
<OutputPath>bin\Debug</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<PlatformTarget>x64</PlatformTarget>
<NoWarn></NoWarn>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors />
<OutputPath>bin\Release</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="System.Configuration" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="someProject.csproj">
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<IncludeAssets>all</IncludeAssets>
</ProjectReference>
</ItemGroup>
<Target DependsOnTargets="ResolveReferences" Name="CopyProjectReferencesToPackage">
<ItemGroup>
<BuildOutputInPackage Include="#(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference'))"/>
</ItemGroup>
</Target>
</Project>

Extract git branch name while building C# project

While building the C# project locally/CI server, I wanted to control the NuGet package reference in the .csproj file. If the developer is building a C# project on github master branch (locally/CI server) I would like to add RC build NuGet package reference otherwise PRE releases NuGet package reference. How to do this? Can someone please assist me?
Some thoughts like -
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<GitBranch>$(GitBranch.Trim())</GitBranch>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GitInfo" Version="2.2.0" />
</ItemGroup>
<Choose>
<When Condition="$(GitBranch) == 'master'">
<ItemGroup>
<PackageReference Include="Data.Account.Domain.Messaging" Version="1.0.0-rc*" IncludePrerelease="true" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<PackageReference Include="Data.Account.Domain.Messaging" Version="1.0.0-pre*" IncludePrerelease="true" />
</ItemGroup>
</Otherwise>
</Choose>
</Project>
You could read the git branch from the .git/HEAD file. Naive implementation like
<PropertyGroup>
<GitBranch>$([System.IO.File]::ReadAlltext('$(MsBuildThisFileDirectory)\.git\HEAD').Replace('ref: refs/heads/', '').Trim())</GitBranch>
</PropertyGroup>
You might want to adjust how you get the path to that file, and perhaps use something more robust (e.g. if you just checkout a random commit in git, the file won't contain a branch name but a commit SHA)
You could also use variable $(GitRoot) from GitInfo itself to build the path, just a small adaption to the existing code but helped for my case where I had to deal with nested folders.
<PropertyGroup>
<GitBranch>$([System.IO.File]::ReadAlltext('$(GitRoot)\.git\HEAD').Replace('ref: refs/heads/', '').Trim())</GitBranch>
</PropertyGroup>

DotNet Core 3.1 - Multiple projects with shared src, obj and bin

I have the following folder structure (following the feature-oriented organization):
Solution
bin
obj
src
Module1
Shared.cs
Module2
Shared.cs
Module3
Shared.cs
Server
Program.cs
Startup.cs
Database
Program.cs
Solution.sln
Server.csproj
Database.csproj
For the Server project I am using Microsoft.NET.Sdk and Microsoft.NET.Sdk.Web for the Database.
Here is the actual Server.csproj:
<Project>
<PropertyGroup>
<TargetFramework>NetCoreApp3.1</TargetFramework>
<Configuration Condition=" '$(Configuration)' == '' ">Development</Configuration>
<EnvironmentName>$(Configuration)</EnvironmentName>
<BaseOutputPath>bin/$(MSBuildProjectName)</BaseOutputPath>
<OutputPath>$(BaseOutputPath)/$(Configuration)</OutputPath>
<BaseIntermediateOutputPath>obj/$(MSBuildProjectName)</BaseIntermediateOutputPath>
<IntermediateOutputPath>$(BaseIntermediateOutputPath)/$(Configuration)</IntermediateOutputPath>
<AppendTargetFrameworkToOutputPath>False</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>False</AppendRuntimeIdentifierToOutputPath>
<EnableDefaultContentItems>False</EnableDefaultContentItems>
<Nullable>Enable</Nullable>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
<RootNamespace>OeMis.Server</RootNamespace>
<StartupObject>OeMis.Server.ServerEntry</StartupObject>
</PropertyGroup>
<ItemGroup>
<Content Include="Configuration.$(Configuration).json" ExcludeFromSingleFile="True" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest"/>
<PackageReference Include="Dapper" Version="2.0.30"/>
<PackageReference Include="HotChocolate" Version="11.0.0-preview.95"/>
<PackageReference Include="HotChocolate.AspNetCore" Version="11.0.0-preview.95"/>
<PackageReference Include="HotChocolate.AspNetCore.Authorization" Version="11.0.0-preview.95"/>
<PackageReference Include="HotChocolate.AspNetCore.Playground" Version="11.0.0-preview.95"/>
<PackageReference Include="Microsoft.Data.SqlClient" Version="2.0.0-preview1.20021.1"/>
</ItemGroup>
<Import Sdk="Microsoft.NET.Sdk.Web" Project="Sdk.props"/>
<Import Sdk="Microsoft.NET.Sdk.Web" Project="Sdk.targets"/>
</Project>
And here is the Database.csproj:
<Project>
<PropertyGroup>
<TargetFramework>NetCoreApp3.1</TargetFramework>
<Configuration Condition=" '$(Configuration)' == '' ">Development</Configuration>
<EnvironmentName>$(Configuration)</EnvironmentName>
<OutputType>Exe</OutputType>
<BaseOutputPath>bin/$(MSBuildProjectName)</BaseOutputPath>
<OutputPath>$(BaseOutputPath)/$(Configuration)</OutputPath>
<BaseIntermediateOutputPath>obj/$(MSBuildProjectName)</BaseIntermediateOutputPath>
<IntermediateOutputPath>$(BaseIntermediateOutputPath)/$(Configuration)</IntermediateOutputPath>
<AppendTargetFrameworkToOutputPath>False</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>False</AppendRuntimeIdentifierToOutputPath>
<EnableDefaultContentItems>False</EnableDefaultContentItems>
<Nullable>Enable</Nullable>
<RootNamespace>OeMis.Database</RootNamespace>
<StartupObject>OeMis.Database.DatabaseEntry</StartupObject>
</PropertyGroup>
<ItemGroup>
<Content Include="Configuration.$(Configuration).json" ExcludeFromSingleFile="True" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest"/>
<PackageReference Include="Dapper" Version="2.0.30"/>
<PackageReference Include="Microsoft.Data.SqlClient" Version="2.0.0-preview1.20021.1"/>
<PackageReference Include="Bogus" Version="29.0.1"/>
</ItemGroup>
<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.props"/>
<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.targets"/>
</Project>
I always get errors in src/Server/Program.cs as if Database.csproj is trying to handle it. The errors have to do with missing references classes in Microsoft.NET.Sdk.Web.
The full project can be found on GitHub
This actually makes sense. You are trying to build the same source files with different dependencies.
My advise is to extract the common/shared items from both and add the to a new project called shared (preferable in .Net standard) and reference the libraries in both your projects.
Creating a class library for .net core guide here
TL;DL;
Create a Solution and Client App.
Create a Class Library Project.
Add Class Library Functionality.
Settings.
Build.
Add Class Library Reference.
Import Namespace.
Call Functions.

Create a self contained exe with a COMReference

I am trying to publish a self contained exe file.
Sadly all my google work was not helpful. I have a COM reference in my code to the WindowsInstaller.
So far this is my csproj file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>MSI_Info</RootNamespace>
<RuntimeIdentifiers>win10-x64;win10-x86</RuntimeIdentifiers>
</PropertyGroup>
<ItemGroup>
<COMReference Include="WindowsInstaller">
<Guid>{000C1092-0000-0000-C000-000000000046}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>1033</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
</ItemGroup>
</Project>
Code is hosted here https://github.com/SmuSmu/MSI-Info
Not so easy to get a simple exe file :)

Build C# standard project with the latest versions of the nuget references

When using new C# projects we don't have packages.config files. The dependencies are specified inside the *.proj file, something like:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="XYZ.Definitions" Version="1.0.0-CI-20181010-102209" />
<PackageReference Include="XYZ.Definitions.Common" Version="1.0.0-CI-20181010-102209" />
</ItemGroup>
</Project>
How can I specify that I always want to build with the latest versions available of my references?
I was thinking something like:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="XYZ.Definitions" Version="latest" />
<PackageReference Include="XYZ.Definitions.Common" Version="latest" />
</ItemGroup>
</Project>
I dont know if this is even possible.
Also here you can find a solution but in another context, that is using packages.config and nuget.config files.
* will use the latest stable version available.
Solution:
<PackageReference Include="XYZ.Definitions" Version="*" />

Categories