Search code examples
c#.netnugetvisual-studio-2022

Unrelated loading error when adding NuGet package information to a .NET framework project


I'm a user of JetBrains products, more specifically the IDE Rider.

My colleague mainly is a user of Microsoft products, more specifically Visual Studio.

So, I was rather surprised, that my solution or c#-projects were broken, when he opened them in Visual Studio. (Properties of specific project)

ms-visual-studio-error

That error is somewhat misleading, because the mentioned constants are actually defined. It is also misleading, because the cause for the error, was the adding of NuGet package information in the .csproj-file.

To me the error is somewhat unrelated to the cause and therefore very confusing on how I should proceed.

Here's the full output of that error:

System.ArgumentException: Expected 1 values for property Build::DefineConstants, but got 0.
Parameter name: values
   at Microsoft.VisualStudio.ProjectSystem.VS.Implementation.PropertyPages.Designer.Property.Update(ImmutableArray`1 values)
   at Microsoft.VisualStudio.ProjectSystem.VS.Implementation.PropertyPages.Designer.Property..ctor(PropertyMetadata metadata, ImmutableArray`1 values, PropertyContext context, ImmutableHashSet`1 varyByDimensions)
   at Microsoft.VisualStudio.ProjectSystem.VS.Implementation.PropertyPages.Designer.PropertyContextFactoryBase.ToProperty(IUIProperty property, Page page, Category category, Int32 order, PropertyContext propertyContext, IPropertyEditorRegistry propertyEditorRegistry)
   at Microsoft.VisualStudio.ProjectSystem.VS.Implementation.PropertyPages.Designer.ProjectPropertyDataAccess.Observer.<HandleDataAsync>g__CreateProperties|14_5(<>c__DisplayClass14_0& )
   at Microsoft.VisualStudio.ProjectSystem.VS.Implementation.PropertyPages.Designer.ProjectPropertyDataAccess.Observer.<HandleDataAsync>g__ProcessInitialData|14_1(<>c__DisplayClass14_0& )
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.ProjectSystem.VS.Implementation.PropertyPages.Designer.ProjectPropertyDataAccess.Observer.<InitializeAsync>d__10.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Microsoft.VisualStudio.ProjectSystem.VS.Implementation.PropertyPages.Designer.ProjectPropertyDataAccess.Observer.<CreateAsync>d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.ProjectSystem.VS.Implementation.PropertyPages.Designer.ProjectPropertiesEditor.<>c__DisplayClass0_0.<<-ctor>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.ProjectSystem.VS.Implementation.PropertyPages.Designer.AsyncLoadContent.<>c__DisplayClass0_0.<<Initialize>b__0>d.MoveNext()

But I can open those project properties without problem in Rider:

jetbrains-rider-project-properties

I've narrowed down the problem to the specific information properties, which I was using to put info in the NuGet package. This documentation/guide mentions that I should be using Assembly Information for that, but I was having problems with the assembly information getting picked up when using nuget pack, which is why I used the properties known to me inside the .csproj-file.

I then resorted to following the informations in the "Create a NuGet package using MSBuild"-Documentation, which was the better option since I could integrate the packaging into the build.

By adding the NuGet-Target-Package, I saw a new tab appear in Rider, which allowed me to edit those informations. That made it feel like I was doing the right thing in Rider, but seeing the results in Visual Studio, makes it look like I'm doing something very unintentional in regards to a NuGet specification I don't know.

EDIT! Here's the full version of the csproj-file


<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{63B8CCEF-5C50-4F25-8E6B-C623DA1BDD2F}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>Testcenter.RobotFramework</RootNamespace>
    <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
    <AssemblyName>Testcenter.RobotFramework</AssemblyName>
    <FileAlignment>512</FileAlignment>
    <DefineConstants>DEBUG</DefineConstants>
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
    <!-- Properties which cause problems in Visual Studio. The error doesn't occur if these are commented out.
    <TargetFramework>netframework4.8</TargetFramework>
    <PackageId>Testcenter.RobotFramework</PackageId>
    <Version>1.0.0</Version>
    <Authors>Testcenter Team, Some Person</Authors>
    <Company>SomeCompany</Company>
    <PackageOutputPath>$(ProjectDir)</PackageOutputPath>
    <Description>A class library to implement a remote library interface conforming to RobotFramework.</Description>
    <Title>RobotFramework Remote-Library-Interface for C#</Title>
    <Copyright>Copyright (c) SomeCompany 2022</Copyright>
    <RepositoryUrl>https://redacted.url.com</RepositoryUrl>
    <Product>Testcenter.RobotFramework</Product>
    <AssemblyVersion>1.0.0</AssemblyVersion>
    <FileVersion>1.0.0</FileVersion> -->
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Testing|AnyCPU' ">
    <OutputPath>bin\Testing\</OutputPath>
    <DefineConstants>TEST</DefineConstants>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Libraries|AnyCPU' ">
    <OutputPath>bin\Libraries\</OutputPath>
    <DefineConstants>ONLY_LIBRARY</DefineConstants>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="mscorlib" />
    <Reference Include="System" />
    <Reference Include="System.ComponentModel.Composition" />
    <Reference Include="System.Configuration" />
    <Reference Include="System.Core" />
    <Reference Include="System.Data" />
    <Reference Include="System.IO.Compression" />
    <Reference Include="System.Xml" />
    <Reference Include="System.Xml.Linq" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Configuration\LibraryConfig.cs" />
    <Compile Include="Configuration\ServerConfiguration.cs" />
    <Compile Include="Configuration\XML\AssemblyElement.cs" />
    <Compile Include="Configuration\XML\AssemblyElementCollection.cs" />
    <Compile Include="Configuration\XML\PortElement.cs" />
    <Compile Include="Configuration\XML\XmlServerConfiguration.cs" />
    <Compile Include="Keyword\IKeywordManager.cs" />
    <Compile Include="Keyword\Keyword.cs" />
    <Compile Include="Keyword\KeywordErrorType.cs" />
    <Compile Include="Keyword\KeywordManager.cs" />
    <Compile Include="Keyword\KeywordResult.cs" />
    <Compile Include="Keyword\KeywordStatus.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="Trash\XmlDocumentation.cs" />
  </ItemGroup>
  <ItemGroup>
    <Content Include="README.md" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="NLog" Version="5.1.0" />
    <PackageReference Include="NuGet.Build.Tasks.Pack" Version="6.4.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Testcenter.RobotFramework.Exceptions" Version="1.0.0" />
    <PackageReference Include="Testcenter.TestAutomation.Utility" Version="1.0.0" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
         Other similar extension points exist, see Microsoft.Common.targets.
    <Target Name="BeforeBuild">
    </Target>
    <Target Name="AfterBuild">
    </Target>
    -->
</Project>

My intention was to embed the NuGet package information in the corresponding project files, without the necessity of creating a .nuspec.

But after encountering that error, it feels like that might have been a misunderstanding.

I am very unsure on what is correct now, in terms of:

  • Where should I place those NuGet-Assembly information, if I were to conform to some "Specification"? (I couldn't find the necessary information)
  • Do I need a NuGet-Spec file in general, when creating NuGet packages from .Net framework packages? (What even is a NuGet-Spec? Why do I need that?)
  • What is the difference between a .Net NuGet package and a .Net framework package?

I found all of this very confusing, because I'm very new when it comes to packaging C#-Projects or creating NuGets.

But I'm forced to work on .NET Framework 4.8, which appearantly makes this process not very straightforward in comparison to .NET core.


Solution

  • Related to the actual error message in your question.

    The DefineConstants error is a bit misleading indeed. I was able to reproduce it starting with your initial .csproj on my machine and narrowing it down to the TargetFramework property.

    Removing

    <TargetFramework>netframework4.8</TargetFramework>
    

    allows the project properties to be opened without errors. Changing it to

    <TargetFramework>net48</TargetFramework>
    

    reintroduces the errors.

    Digging some more, it appears to be an issue with whether the Visual Studio instance has .NET Framework 4.8 SDK vs .NET Framework 4.8 targeting pack installed (ref Visual Studio Can't Target .NET Framework 4.8). Also see the target frameworks docs.

    Additionally, it helps to identify your correct project format, to figure out how to proceed.

    Yours is a migrated Non-SDK project using NuGet.Build.Tasks.Pack.

    The correct syntax is to use TargetFrameworkVersion only.

    <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
    

    (Apperantly there is no more documentation about this)


    Related to the NuGet part of your question

    The NuGet part of your question doesn't actually relate to the error you're getting at all, but I'll answer your points.

    My intention was to embed the NuGet package information in the corresponding project files, without the necessity of creating a .nuspec.

    That's fine, and that's supported in both NuGet package/publish scenarios (.NET and .NET Framework). In fact, it's encouraged. You will need to read the docs to understand which ones matter for NuGet.

    But after encountering that error, it feels like that might have been a misunderstanding.

    Yes

    Where should I place those NuGet-Assembly information...

    Generally in the .csproj and/or using assembly attributes for things like version, etc.

    Do I need a NuGet-Spec file in general, when creating NuGet packages from .Net framework packages? (What even is a NuGet-Spec? Why do I need that?)

    Yes, it's a manifest file and gets embedded into the NuGet package. If you put the properties in the csproj file, this is generated and you don't have to manually create it.

    What is the difference between a .Net NuGet package and a .Net framework package?

    From the perspective of NuGet package managers, nothing really. Package managers of all kinds need a manifest, need package contents (assemblies and any other content), and need to install the package the way the author intends.

    From the perspective of packaging/publishing the steps are basically the same, but the tooling is different.

    Finally...

    As an experiment if you have access to a VS instance that has ReSharper enabled, you can try out the ReSharper based build. I'm pretty sure it doesn't use MSBuild either, and so might be interesting to see if your error occurs with that.