Nuget PackageReference found in one solution, but not in my own solution - c#

Previous title:
The "GenerateFileFromTemplate" task was not found
.NET project template - GeneratedContent
.csproj.in file transformations
The troubled package is Microsoft.DotNet.Build.Tasks.Templating.
I've created a git-repository containing multiple .NET project templates. When opened in Visual Studio, VS had a horrible performance when adding more files to the template project. This turned out to be caused by my template's project files having .csproj extension. Therefor I've changed the extensions of all my template csproj files to csproj.in.
Because of this, I need to add a msbuild task that transforms this .csproj.in to .csproj. There are several examples out on the internet:
ASP.NET Core project templates
spa-templates (Seems to use the Arcade SDK)
dotnet-template-samples (very basic)
microsoft/SEAL
In the above samples, there is no nuget.config in the project.
Your root csproj file contains a <GeneratedContentProperties> and <GeneratedContent> section:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<GeneratedContentProperties>
DefaultNetCoreTargetFramework=$(DefaultNetCoreTargetFramework);
</GeneratedContentProperties>
</PropertyGroup>
<ItemGroup>
<GeneratedContent Include="Angular-CSharp.csproj.in" OutputPath="content/Angular-CSharp/Company.WebApplication1.csproj" />
<GeneratedContent Include="React-CSharp.csproj.in" OutputPath="content/React-CSharp/Company.WebApplication1.csproj" />
</ItemGroup>
</Project>
The .csproj.in files reference the GeneratedContentProperties:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>${DefaultNetCoreTargetFramework}</TargetFramework>
...
</PropertyGroup>
...
</Project>
I've tried applying the same files to my project in this commit, but I'm still getting the following error when building the project:
dotnet build --configuration Release
MSBuild version 17.3.0+92e077650 for .NET
Determining projects to restore...
C:\Program Files\dotnet\sdk\6.0.400\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.DefaultItems.Shared.targets(152,5): warning NETSDK1023: A PackageReference for 'Microsoft.DotNet.Build.Tasks.Templating' was included in your project. This package is implicitly referenced by the .NET SDK and you do not typically need to reference it from your project. For more information, see https://aka.ms/sdkimplicitrefs [C:\repos\MintPlayer.AspNetCore.Templates\MintPlayer.AspNetCore.
IdentityServer.Templates\MintPlayer.AspNetCore.IdentityServer.Templates.csproj]
...
All projects are up-to-date for restore.
...
C:\repos\MintPlayer.AspNetCore.Templates\eng\GenerateContent.targets(27,3): error MSB4036: The "GenerateFileFromTemplate" task was not found. Check the following:
1.) The name of the task in the project file is the same as the name of the task class.
2.) The task class is "public" and implements the Microsoft.Build.Framework.ITask interface.
3.) The task is correctly declared with <UsingTask> in the project file, or in the *.tasks files located in the "C:\Program Files\dotnet\sdk\6.0.400" directory
[C:\repos\MintPlayer.AspNetCore.Templates\MintPlayer.AspNetCore.IdentityServer.Templates\MintPlayer.AspNetCore.IdentityServer.Templates.csproj]
Build FAILED.
It seems that dotnet cannot find the GenerateFileFromTemplate Task...
I also see that the spa-templates project is using the Arcade SDK, but I don't think I'd actually need that...
How can I fix this? What am I still missing here?
EDIT
When I open both projects in Visual Studio, this is what I see:
Nuget packages for my template project:
C:\repos\MintPlayer.AspNetCore.Templates\MintPlayer.AspNetCore.IdentityServer.Templates> dotnet restore
Determining projects to restore...C:\repos\MintPlayer.AspNetCore.Templates\MintPlayer.AspNetCore.IdentityServer.Templates\MintPlayer.AspNetCore.IdentityServer.Templates.csproj : warning NU1604: Project dependency Microsoft.DotNet.Build.Tasks.Templating does not contain an inclusive lower bound.
Include a lower bound in the dependency version to ensure consistent restore results.
C:\repos\MintPlayer.AspNetCore.Templates\MintPlayer.AspNetCore.IdentityServer.Templates\MintPlayer.AspNetCore.IdentityServer.Templates.csproj : error NU1101: Unable to find package Microsoft.DotNet.Build.Tasks.Templating. No packages exist with this id in source(s): C:\Program Files\dotnet\library-packs, Local, Microsoft Visual Studio Offline Packages, nuget.org
Failed to restore C:\repos\MintPlayer.AspNetCore.Templates\MintPlayer.AspNetCore.IdentityServer.Templates\MintPlayer.AspNetCore.IdentityServer.Templates.csproj (in 516 ms).
Nuget packages for spa-templates:
C:\repos\spa-templates\src> dotnet restore
Determining projects to restore...
C:\repos\spa-templates\src\Microsoft.DotNet.Web.Spa.ProjectTemplates.csproj : warning NU1603: Microsoft.DotNet.Web.Spa.ProjectTemplates.7.0 depends on Microsoft.DotNet.Build.Tasks.Templating (>= 6.0.0-beta.21373.11) but Microsoft.DotNet.Build.Tasks.Templating 6.0.0-beta.21373.11 was not found. An approximate best match of Microsoft.DotNet.Build.Tasks.Templating 6.0.0-beta.22212.5 was resolved.
All projects are up-to-date for restore.
So it seems that dotnet restore is unable to restore this package. However, the nuget sources are the same for both projects:
IdentityServer.Templates>dotnet nuget list source
Registered Sources:
1. nuget.org [Enabled]
https://api.nuget.org/v3/index.json
2. Local [Enabled]
C:\packages
3. Microsoft Visual Studio Offline Packages [Enabled]
C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\
C:\repos\spa-templates>dotnet nuget list source
Registered Sources:
1. nuget.org [Enabled]
https://api.nuget.org/v3/index.json
2. Local [Enabled]
C:\packages
3. Microsoft Visual Studio Offline Packages [Enabled]
C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\
EDIT 2
Hmm, it seems that GenerateFileFromTemplate is part of the Arcade SDK... (Howto)

How to install Microsoft.DotNet.Arcade.Sdk into the dotnet sdk folder?
It seems that the package is only available through the following NuGet feed:
https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json
So I added a nuget.config in the root of the project/repository:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" />
</packageSources>
</configuration>
And since there's only preview versions of the package, you need for example the following version (eng/Versions.props):
<Project>
...
<PropertyGroup Label="Package versions">
<MicrosoftDotNetBuildTasksTemplatingVersion>6.0.0-beta.21373.11</MicrosoftDotNetBuildTasksTemplatingVersion>
...
</PropertyGroup>
</Project>

Related

Problem after transferring files to another system (error NETSDK1)

After I import the files from another system to my system, I get the following error
Severity Code Description Project File Line Suppression State
Error NETSDK1005 Assets file 'C:\Users\user\Desktop\project1\project1\project1\obj\project.assets.json' doesn't have a target for 'net5.0'. Ensure that restore has run and that you have included 'net5.0' in the TargetFrameworks for your project. project1 C:\Program Files\dotnet\sdk\6.0.301\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets 267
Update to Nuget 5.8 Clear the local cache
error NETSDK1005: Assets file 'project.assets.json' ....
Try updating NuGet.exe to the 5.8.0 version or above:
nuget update -self
if you prefer to update the nuget version in Visual Studio, just follow this steps. Then, clear NuGet cache:
dotnet nuget locals all --clear
reference

C#/.NET - How to generate and increase package version automatically especially via CI?

I have a Visual Studio project which is built as a NuGet lib package. But every time I publish the package, I have to change the version number manually. That's a prone-to-error work.
I'd like to generate and increase the package version number automatically.
I found GitVersion tool to solve this problem. And I also found some semantic versioning blogs to explain the package version of continuous delivery.
GitTools/GitVersion: Easy Semantic Versioning (http://semver.org) for projects using Git
GitVersion Documentation
Versioning NuGet packages in a continuous delivery world: part 1 – Microsoft DevOps Blog
Versioning NuGet packages in a continuous delivery world: part 2 – Microsoft DevOps Blog
Versioning NuGet packages in a continuous delivery world: part 3 – Microsoft DevOps Blog
But unfortunately, The GitVersion package does not work correctly for me.
It gives me an error that AssemblyVersionAttribute is duplicated.
If I add <GenerateAssemblyInfo>false</GenerateAssemblyInfo> into the csproj file, It will do nothing and the package version will be 0.0.0.0.
Maybe the reason is that I'm using the new csproj format. See here to view the csproj file and the file looks like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net45;net47;netstandard2.0</TargetFrameworks>
</PropertyGroup>
</Project>
Any reply is appreciated.
UPDATE:
I find that there is an issue to mention my problem: Gitversion Task for VS2017-style csproj · Issue #1349 · GitTools/GitVersion. I'm trying the new solution.
Not sure about Jenkins, but it should be able to generate an incremental number or timestamp by itself that can be accessed via an environment variable on your build pipeline.
I think the most flexible way is to add a PackageVersion tag with a placeholder to your csproj that your build pipeline can then change:
<PropertyGroup>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageVersion>$(PackageVersion)</PackageVersion>
</PropertyGroup>
So, on your build pipeline, you just pass the version, for example:
dotnet build -p:PackageVersion=$(BUILD_TIMESTAMP)
We can trigger the GitHub Action by Git tag pushed and we can read the Git tag name as the version. And then we can generate the NuGet package with this version.
There is a dotnet tool that can read Git tags as a version and write it to the version file.
Before using it, we should create the version file and import the version file.
We should use dotnet to install the dotnetCampus.TagToVersion tool and use the tool to write the Git tag to version file.
The step 1:
Adding the Directory.Build.props file to repo folder.
Writing the code to the Directory.Build.props file.
<Project>
<Import Project="build\Version.props" />
</Project>
The step 2:
Making a folder named build and adding the Version.props file to this folder.
Writing the code to the build\Version.props file.
<Project>
<PropertyGroup>
<Version>1.0.5</Version>
</PropertyGroup>
</Project>
The step 3:
Writing a GitHub Action configuration file in .github\workflows folder, for example create the .github\workflows\push tag and pack nuget.yml file
Making the Action trigger by tag push.
on:
push:
tags:
- '*'
Writing the tag as version by dotnet tool.
- name: Install dotnet tool
run: dotnet tool install -g dotnetCampus.TagToVersion
- name: Set tag to version
run: dotnet TagToVersion -t ${{ github.ref }}
Building the package
# Build and publish
- name: Build with dotnet
run: dotnet build --configuration Release
- name: Install Nuget
uses: nuget/setup-nuget#v1
with:
nuget-version: '5.x'
- name: Add private GitHub registry to NuGet
run: |
nuget sources add -name github -Source https://nuget.pkg.github.com/ORGANIZATION_NAME/index.json -Username ORGANIZATION_NAME -Password ${{ secrets.GITHUB_TOKEN }}
- name: Push generated package to GitHub registry
run: |
nuget push .\bin\release\*.nupkg -Source github -SkipDuplicate
nuget push .\bin\release\*.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NugetKey }} -NoSymbols
See https://github.com/dotnet-campus/dotnetCampus.TagToVersion
Actually GitVersionTask is not hard to use. All that you should do is these things below:
Install GitVersionTask from NuGet.
Add a configuration file named GitVersion.yml with some key-values.
Add a tag to your branch.
Build.
After doing that, you can find your output dll file contains a semantic version.
I'm answering my own question because I just wrote the wrong config file name. So it did not work correctly.
This is my configuration file:
mode: ContinuousDelivery
increment: Inherit
tag-prefix: '[vV]'
source-branches: ['master', 'develop', 'hotfix']
branches:
master:
regex: master$
mode: ContinuousDelivery
tag: ''
increment: Patch
prevent-increment-of-merged-branch-version: true
track-merge-target: false
tracks-release-branches: false
is-release-branch: true
release:
regex: r(elease$|(eleases)?[-/])
mode: ContinuousDelivery
tag: beta
increment: Patch
prevent-increment-of-merged-branch-version: true
track-merge-target: false
tracks-release-branches: false
is-release-branch: true
feature:
regex: f(eatures)?[-/]
mode: ContinuousDeployment
tag: alpha
increment: Minor
prevent-increment-of-merged-branch-version: false
track-merge-target: false
tracks-release-branches: false
is-release-branch: false
I've posted this configuration file content here: Automatically increase the semantic version using GitVersion - walterlv

How to publish for all target frameworks

I am building a set of build template in TeamCity for .Net Core projects. Everything is working great, except for console projects. The problem is that when I go to publish the solution, I need to specify the framework version. At no other point in the build do I need to know the framework. At least this is true when publishing .sln files, with a console project that only has a single framework targeted.
So now I am in a situation where I need to figure out what framework the console project should target. I could read various XML files, but I'm hoping I don't need to. Is there some builtin way that I can query for the frameworks in use for a given solution?
For example, something like (PowerShell)
$frameworks = & dotnet.exe --<what I want> .\MySolution.sln
for ($framework in $frameworks) {
& dotnet.exe publish -f $framework .\MySolution.sln
}
That way I don't need to modify the build system every time a new framework is in use. I've poked around in the CLI repo, but I can't find a command that does what I need. Is opening .csproj files my only hope?
If you want to publish projects that target multiple frameworks, the default Publish target fails, but you can create a custom target that performs the multi-targeting itself. To do this, create a file named Directory.Build.props in the solution folder (with MSBuild > 15.1 this can and should be named Directory.Build.targets because there was a bug with multi-targeting projects):
<Project>
<Target Name="PublishProjectIfFrameworkSet"
DependsOnTargets="Publish"
Condition=" '$(TargetFramework)' != '' " />
<Target Name="PublishProjectForAllFrameworksIfFrameworkUnset" Condition=" '$(TargetFramework)' == '' ">
<ItemGroup>
<_PublishFramework Include="$(TargetFrameworks)" />
</ItemGroup>
<MSBuild Projects="$(MSBuildProjectFile)" Targets="Publish" Properties="TargetFramework=%(_PublishFramework.Identity)" />
</Target>
<Target Name="PublishAll"
DependsOnTargets="PublishProjectIfFrameworkSet;PublishProjectForAllFrameworksIfFrameworkUnset" />
</Project>
Then you can publish the projects for all defined frameworks by executing this in the solution directory:
$ dotnet msbuild /t:PublishAll /p:Configuration=Release
Microsoft (R) Build Engine version 15.1.1012.6693
Copyright (C) Microsoft Corporation. All rights reserved.
app2 -> /Users/martin/testproj/app2/bin/Release/netcoreapp1.1/app2.dll
app1 -> /Users/martin/testproj/app1/bin/Release/netcoreapp1.1/app1.dll
app1 -> /Users/martin/testproj/app1/bin/Release/netcoreapp1.0/app1.dll

How to run MSBuild pack target in Visual Studio 2017

My question is similar to this and this.
I want to package a .Net Framework library in Visual Studio 2017 RC. In VS 2015 with project.json build system, I was able to accomplish this by importing a custom targets file into the .xproj file. This custom targets file took care of creating the nuspec file if it didn't exist, then running nuget pack, copying the resulting packages to local feed location, etc.
Do I need to do something similar in 2017 (haven't made a serious effort yet) or can I somehow enable the pack target in my .csproj file?
The docs here only show to run the pack target from the command line.
EDIT:
I'm trying the below custom target referencing a Nuget 4.0 exe from the nightly builds...
<Target Name="PackNugets" AfterTargets="Build">
<PropertyGroup>
<NugetV4Path>$([System.IO.Path]::GetFullPath('path to nuget.exe'))</NugetV4Path>
</PropertyGroup>
<Exec Command=""$(NugetV4Path)\nuget.exe" pack "$(MSBuildProjectDirectory)\$(PackageId).csproj" -Symbols -OutputDirectory bin -Properties Configuration=Release"/>
</Target>
But I get the following error
System.InvalidCastException: Unable to cast object of type 'System.String' to type 'NuGet.Frameworks.NuGetFramework'.
at NuGet.ProjectManagement.NuGetProject.GetMetadata[T](String key)
at NuGet.ProjectManagement.PackagesConfigNuGetProject..ctor(String folderPath, Dictionary`2 metadata)
at CallSite.Target(Closure , CallSite , Type , Object , Dictionary`2 )
at System.Dynamic.UpdateDelegates.UpdateAndExecute3[T0,T1,T2,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2)
at NuGet.CommandLine.ProjectFactory.AddDependencies(Dictionary`2 packagesAndDependencies)
at NuGet.CommandLine.ProjectFactory.ProcessDependencies(PackageBuilder builder)
at NuGet.CommandLine.ProjectFactory.CreateBuilder(String basePath, NuGetVersion version, String suffix, Boolean buildIfNeeded, PackageBuilder builder)
at NuGet.Commands.PackCommandRunner.BuildFromProjectFile(String path)
at NuGet.CommandLine.PackCommand.ExecuteCommand()
at NuGet.CommandLine.Command.ExecuteCommandAsync()
at NuGet.CommandLine.Command.Execute()
at NuGet.CommandLine.Program.MainCore(String workingDirectory, String[] args)
Something to do with one of the properties in the csproj? Does NugetFramework refer to the TargetFramework?
I am targeting net452 in my csproj, in case that helps.
EDIT:
That exception is indeed about nuget attempting to parse the TargetFramework, but it is not clear whether it is failing at my csproj or at a dependency...
EDIT: The latest updates to VS2017 have added the Pack action to the project context menu, so the below action can be changed as follows:
AfterTargets=Pack
Remove the Exec element
If you are targeting multiple frameworks, you may have to insert a \$(Configuration) after the \bin in the NugetPackages Include.
Ok, this issue solved it for me. For now, we have to use dotnet instead of msbuild or nuget.
So, my custom target in the imported .targets file becomes
<Project ToolsVersion="15.0">
<Target Name="PackNugets" AfterTargets="AfterBuild">
<!-- Swap out nuget for dotnet and update the cli args -->
<!-- Might actually be able to leave out the csproj path, since
this target should run in the project directory. Test it first. -->
<Exec Command="dotnet pack "$(MSBuildProjectDirectory)\$(PackageId).csproj" --no-build --include-symbols -o bin -c Release"/>
<!-- If you want to copy to a local feed -->
<ItemGroup>
<NugetPackages Include="$(MSBuildProjectDirectory)\bin\$(PackageId).$(PackageVersion)*.nupkg"/>
</ItemGroup>
<Copy SourceFiles="#(NugetPackages)" DestinationFolder="path to local feed" />
</Target>
</Project>
I was wanting to know the same thing, so I went spelunking in the MSBuild files, namely: C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Sdks\NuGet.Build.Tasks.Pack\build and look for the "Pack" target.
Beyond that, I would refer to general MSBuild command line syntax here, but a few examples:
msbuild.exe -t:Pack -p:IncludeSymbols=true
msbuild.exe -t:Pack -p:Configuration=Release -p:VersionSuffix="alpha" # or "-alpha" - not sure
EDIT: A little more research and work on my scenario and I found this documentation of the important properties.
Please note that dotnet pack or msbuild /t:Pack currently doesn't support .NET Framework projects. They only work NETCore projects.
You can even improve Ken G answer if you want to push the nuget using this:
<Target Name="PushNugetPackage" AfterTargets="Pack" Condition="'$(Configuration)' == 'Release'">
<Exec Command="nuget.exe push -Source "mysource" -ApiKey VSTS $(OutputPath)..\$(PackageId).$(PackageVersion).nupkg" />
</Target>
It will only run after you choose pack from context menu and configuration is Release, so you don't push debug packages, remove that condition if you really don't need it
Source

How I pack a multi-target package with MSBuild 15?

I am using the new MSBuild 15 distributed with VS2017 RC to compile and pack a multi targeting project.
Restoring: msbuild /t:restore mysolution.sln works correctly.
Building: msbuild /p:Configuration=Release mylibrary.csproj works correctly and generates:
+ bin/Release
+ netstandard1.4
- mylibrary.dll
+ net452
- mylibrary.dll
But when I am packing: msbuild /t:pack /p:Configuration=Release /p:IncludeSymbols=true mylibrary.csproj the structure does not match well with the previous build, looking like:
+ bin/Release
+ netstandard1.4
- mylibrary.pdb
+ net452
- mylibrary.pdb
- mylibrary.dll
Warnings from the /t:pack command show me this was gonna happen, but not sure how to solve it:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Sdks\NuGet.Build.Tasks.Pack\buildCrossTargeting\NuGet.Build.Tasks.Pack.targets(73,5): warning : Issue found with package 'MyLibrary'. [D:\XXX\YYY\src\MyLibrary\MyLibrary.csproj]
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Sdks\NuGet.Build.Tasks.Pack\buildCrossTargeting\NuGet.Build.Tasks.Pack.targets(73,5): warning : Issue: Assembly not inside a framework folder. D:\XXX\YYY\src\MyLibrary\MyLibrary.csproj]
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Sdks\NuGet.Build.Tasks.Pack\buildCrossTargeting\NuGet.Build.Tasks.Pack.targets(73,5): warning : Description: The assembly 'lib\MyLibrary.dll' is placed directly under 'lib' folder. It is recommended that assemblies be placed inside a framework-specific folder.
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Sdks\NuGet.Build.Tasks.Pack\buildCrossTargeting\NuGet.Build.Tasks.Pack.targets(73,5): warning : Solution: Move it into a framework-specific folder. If this assembly is targeted for multiple frameworks, ignore this warning.
Notes:
I am not using a *.nuspec file. Just the new way *.csproj files work (https://docs.nuget.org/ndocs/schema/msbuild-targets#pack-target)
This is how some of the relevant content of the file look like:
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<OutputType>library</OutputType>
<TargetFrameworks>netstandard1.4;net452</TargetFrameworks>
<AssemblyName>MyLibrary</AssemblyName>
<Authors>XXX</Authors>
<Description>YYY</Description>
<PackageId>MyLibrary</PackageId>
<PackageVersion>1.2.3</PackageVersion>
</PropertyGroup>
</Project>
Thanks for your comments. I found my way on based on them.
This is what I did: I downloaded the dotnet cli tool again and test it from scratch. I realized that the version of the cli tool were the same so I started comparing the files inside.
Wrong dotnet cli version
The version that was not working contained the following files:
+ dotnet
+ sdk
+ 1.0.0-preview2-1-003177
+ 1.0.0-preview2-003131
+ 1.0.0-preview2-003133
+ 1.0.0-preview4-004233
Using dotnet build /t:pack /p:Configuration=Release /p:IncludeSymbols=true mylibrary.csproj showed the following error:
Couldn't find 'project.json' in '/t:pack'
Good dotnet cli version
The second version I downloaded contained only these:
+ dotnet
+ sdk
+ 1.0.0-preview4-004233
And executing the command before, it works correctly:
Microsoft (R) Build Engine version 15.1.458.808
Copyright (C) Microsoft Corporation. All rights reserved.
...

Categories