A Comprehensive Guide to Setting Version Numbers in .NET Core CSPROJ Projects

Dec 01, 2025 · Programming · 26 views · 7.8

Keywords: .NET Core | Version Management | CSPROJ | Continuous Integration | Command-Line Arguments

Abstract: This article explores how to effectively set version numbers in CI environments after .NET Core's migration from JSON to CSPROJ project files. By analyzing the mechanism of generating AssemblyInfo.cs files, it details methods such as overriding properties via command-line arguments, version composition logic, and conditional settings using environment variables. Practical examples and best practices are provided to help developers achieve unified and flexible version management strategies.

Introduction

With the release of .NET Core 1.1 and Visual Studio 2017, project file formats have migrated from JSON to CSPROJ, introducing new challenges in version management. In continuous integration (CI) environments, developers often need to dynamically set version numbers to stamp builds. Traditional methods like using SharedAssemblyInfo.cs files can lead to CS0579 duplicate attribute errors, as the build process automatically generates an AssemblyInfo.cs file. Based on high-scoring answers from Stack Overflow, this article systematically explains how to effectively control version numbers through CSPROJ files.

Internal Mechanism of Version Generation

When building a .NET Core project, MSBuild generates an AssemblyInfo.cs file in the \obj\Debug\netcoreapp1.1 directory, containing attributes such as AssemblyFileVersionAttribute and AssemblyVersionAttribute. These attributes are derived from settings in the CSPROJ file, for example:

<PropertyGroup>
  <Version>1.0.7777.0</Version>
  <AssemblyVersion>1.0.8888.0</AssemblyVersion>
  <FileVersion>1.0.9999.0</FileVersion>
</PropertyGroup>

Manually adding these attributes to code can conflict with the generated file, causing compilation errors. Therefore, the correct approach is to control versions by modifying CSPROJ properties or using command-line arguments.

Overriding Version Properties via Command-Line Arguments

In CI scripts, the most direct method is to override properties using the /p:PropertyName=Value parameter with dotnet commands. For example, to set the assembly version:

dotnet build /p:AssemblyVersion=1.2.3.4

This works with dotnet restore, dotnet build, and dotnet pack commands. The version composition logic is as follows: if the Version property is unset, VersionPrefix (defaulting to 1.0.0) is used, with an optional VersionSuffix appended. Other version properties (e.g., AssemblyVersion and FileVersion) default to the Version value. For instance, set <VersionPrefix>1.2.3</VersionPrefix> in the CSPROJ, then run:

dotnet pack --version-suffix beta1

This will produce YourApp.1.2.3-beta1.nupkg. Note that if project references require the version suffix, run dotnet restore /p:VersionSuffix=beta1 first to avoid a known bug in the tooling.

Advanced Version Management Strategies

For complex scenarios, such as generating both services and NuGet packages, it is recommended to use conditional logic in the CSPROJ. For example, dynamically set the version via an environment variable RELEASE_VERSION:

<Version Condition="'$(RELEASE_VERSION)' != ''">$(RELEASE_VERSION)</Version>
<VersionPrefix Condition="'$(RELEASE_VERSION)' == ''">0.0.1</VersionPrefix>
<VersionSuffix Condition="'$(RELEASE_VERSION)' == ''">$([System.DateTime]::UtcNow.ToString(`yyyyMMdd-HHmm`))</VersionSuffix>

After setting the environment variable in the CI script, running dotnet build will automatically apply the version. This method avoids the "hacky" approach of manually editing CSPROJ files and ensures consistency.

Practical Application Examples

When publishing software, distinguish between file version and product version. For example:

dotnet publish .\ProjectFolder\Project.csproj -r win-x64 /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true --self-contained true -o ReleaseFolderName -c Release /p:AssemblyVersion=1.2.3.4 /p:Version=1.2.3.4-product-version

This will display the corresponding version information in the generated EXE file properties. Developers should refer to the Microsoft.NET.GenerateAssemblyInfo.targets source file to understand all supported properties, such as AssemblyCompanyAttribute and AssemblyProductAttribute.

Conclusion

In .NET Core CSPROJ projects, version management should be implemented via command-line arguments or conditional settings in CSPROJ, rather than directly modifying code. This ensures flexibility and maintainability in CI environments. By combining VersionPrefix, VersionSuffix, and environment variables, developers can build unified version strategies applicable from development to production.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.