47

What are the options for setting a project version with .NET Core / ASP.NET Core projects?

Found so far:

  • Set the version property in project.json. Source: DNX Overview, Working with DNX projects. This seems to set the AssemblyVersion, AssemblyFileVersion and AssemblyInformationalVersion unless overridden by an attribute (see next point).

  • Setting the AssemblyVersion, AssemblyFileVersion, AssemblyInformationalVersion attributes also seems to work and override the version property specified in project.json.

    For example, including 'version':'4.1.1-*' in project.json and setting [assembly:AssemblyFileVersion("4.3.5.0")] in a .cs file will result in AssemblyVersion=4.1.1.0, AssemblyInformationalVersion=4.1.1.0 and AssemblyFileVersion=4.3.5.0

Is setting the version number via attributes, e.g. AssemblyFileVersion, still supported?

Have I missed something - are there other ways?

Context

The scenario I'm looking at is sharing a single version number between multiple related projects. Some of the projects are using .NET Core (project.json), others are using the full .NET Framework (.csproj). All are logically part of a single system and versioned together.

The strategy we used up until now is having a SharedAssemblyInfo.cs file at the root of our solution with the AssemblyVersion and AssemblyFileVersion attributes. The projects include a link to the file.

I'm looking for ways to achieve the same result with .NET Core projects, i.e. have a single file to modify.

Ronald Zarīts
  • 11,819
  • 8
  • 39
  • 42
  • 1
    Source links are no longer pointing at anything. – Robert Schmidt Oct 22 '16 at 14:24
  • Updated link to DNX Overview: http://dotnet.today/en/aspnet5-vnext/dnx/overview.html – Arthur Stankevich Nov 25 '16 at 11:10
  • Thanks, @ArthurStankevich, but the link isn't up to date with the current state of .NET Core. DNX was removed from .NET Core and .NET CLI should be used instead. [Migration guide](https://learn.microsoft.com/en-us/dotnet/articles/core/migrating-from-dnx). That doesn't affect versioning, though. That said, I should update the question. – Ronald Zarīts Nov 25 '16 at 14:20
  • 2
    you could use [dotnet-bump](https://github.com/BalassaMarton/dotnet-bump) – Dalton Jan 04 '17 at 10:02

6 Answers6

28

You can create a Directory.Build.props file in the root/parent folder of your projects and set the version information there.

However, now you can add a new property to every project in one step by defining it in a single file called Directory.Build.props in the root folder that contains your source. When MSBuild runs, Microsoft.Common.props searches your directory structure for the Directory.Build.props file (and Microsoft.Common.targets looks for Directory.Build.targets). If it finds one, it imports the property. Directory.Build.props is a user-defined file that provides customizations to projects under a directory.

For example:

<Project>
  <PropertyGroup>
    <Version>0.0.0.0</Version>
    <FileVersion>0.0.0.0</FileVersion>
    <InformationalVersion>0.0.0.0.myversion</InformationalVersion>
  </PropertyGroup>
</Project>
TommyN
  • 2,252
  • 22
  • 19
21

Another option for setting version info when calling build or publish is to use the undocumented /p option.

dotnet command internally passes these flags to MSBuild.

Example:

dotnet publish ./MyProject.csproj /p:Version="1.2.3" /p:InformationalVersion="1.2.3-qa"

See here for more information: https://github.com/dotnet/docs/issues/7568

Arnold Zokas
  • 8,306
  • 6
  • 50
  • 76
  • 1
    This works for `dotnet nuget pack` as well, which I need. – Luke Vo Apr 14 '20 at 03:58
  • Where can I find a list of project-level properties I can set with the `/p:` command? – PGmath Sep 16 '20 at 16:59
  • @PGmath don't know if there is a comprehensive list somewhere that shows all project-level properties, but common and reserved properties are documented https://learn.microsoft.com/en-us/visualstudio/msbuild/common-msbuild-project-properties?view=vs-2019 and https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild-reserved-and-well-known-properties?view=vs-2019. What are you trying to accomplish? Questions in comments have poor visibility - you may want to ask this as a separate question. – Arnold Zokas Sep 18 '20 at 10:02
  • 1
    The syntax seems to currently be `-p` https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-publish#msbuild – Simopaa Mar 01 '21 at 06:20
  • how to set in VS2019? – huang May 15 '21 at 18:01
  • `/p:AssemblyVersion=1.0.42` as well as `Version` worked for me – DaveD Dec 05 '21 at 00:38
2

Not sure if this helps, but you can set version suffixes at publish time. Our versions are usually datetime driven, so that developers don't have to remember to update them.

If your json has something like "1.0-*"

"dotnet publish --version-suffix 2016.01.02" will make it "1.0-2016.01.02".

It's important to stick to "semvar" standards, or else you'll get errors. Dotnet publish will tell you.

Ralph N
  • 4,240
  • 8
  • 28
  • 36
  • 4
    This only sets the `AssemblyInformationalVersion` and doesn't modify `AssemblyFileVersion` or `AssemblyVersion`. – Gabriel Jan 18 '17 at 23:16
2

Why not just change the value in the project.json file. Using CakeBuild you could do something like this (optimizations probably possible)

Task("Bump").Does(() => {
    var files = GetFiles(config.SrcDir + "**/project.json");
    foreach(var file in files)
    {
        Information("Processing: {0}", file);

        var path = file.ToString();
        var trg = new StringBuilder();
        var regExVersion = new System.Text.RegularExpressions.Regex("\"version\":(\\s)?\"0.0.0-\\*\",");
        using (var src = System.IO.File.OpenRead(path))
        {
            using (var reader = new StreamReader(src))
            {
                while (!reader.EndOfStream)
                {
                    var line = reader.ReadLine();
                    if(line == null)
                        continue;

                    line = regExVersion.Replace(line, string.Format("\"version\": \"{0}\",", config.SemVer));

                    trg.AppendLine(line);
                }
            }
        }

        System.IO.File.WriteAllText(path, trg.ToString());
    }
});

Then if you have e.g. a UnitTest project that takes a dependency on the project, use "*" for dependency resolution.

Also, do the bump before doing dotnet restore. My order is as follows:

Task("Default")
  .IsDependentOn("InitOutDir")
  .IsDependentOn("Bump")
  .IsDependentOn("Restore")
  .IsDependentOn("Build")
  .IsDependentOn("UnitTest");

Task("CI")
  .IsDependentOn("Default")
  .IsDependentOn("Pack");

Link to full build script: https://github.com/danielwertheim/Ensure.That/blob/3a278f05d940d9994f0fde9266c6f2c41900a884/build.cake

The actual values, e.g. the version is coming from importing a separate build.config file, in the build script:

#load "./buildconfig.cake"

var config = BuildConfig.Create(Context, BuildSystem);

The config file looks like this (taken from https://github.com/danielwertheim/Ensure.That/blob/3a278f05d940d9994f0fde9266c6f2c41900a884/buildconfig.cake):

public class BuildConfig
{
    private const string Version = "5.0.0";

    public readonly string SrcDir = "./src/";
    public readonly string OutDir = "./build/";    

    public string Target { get; private set; }
    public string Branch { get; private set; }
    public string SemVer { get; private set; }
    public string BuildProfile { get; private set; }
    public bool IsTeamCityBuild { get; private set; }

    public static BuildConfig Create(
        ICakeContext context,
        BuildSystem buildSystem)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        var target = context.Argument("target", "Default");
        var branch = context.Argument("branch", string.Empty);
        var branchIsRelease = branch.ToLower() == "release";
        var buildRevision = context.Argument("buildrevision", "0");

        return new BuildConfig
        {
            Target = target,
            Branch = branch,
            SemVer = Version + (branchIsRelease ? string.Empty : "-b" + buildRevision),
            BuildProfile = context.Argument("configuration", "Release"),
            IsTeamCityBuild = buildSystem.TeamCity.IsRunningOnTeamCity
        };
    }
}
Daniel
  • 8,133
  • 5
  • 36
  • 51
  • Good one but they may be using the CakeBuild. – Ostati Jan 24 '17 at 14:46
  • won't this replace version attributes of dependencies too? e.g., "dependencies": { "Microsoft.NETCore.App": { "version": "1.0.1", "type": "platform" }, – Kevin Feb 01 '17 at 16:13
2

If you still want to have the Solution Level SharedVersionInfo.cs you can do it by adding these lines to your project.json file:

"buildOptions": {
  "compile": {
    "includeFiles": [
      "../../SharedVersionInfo.cs"
    ]
  }
}

Your relative path may vary, of course.

Jesse Chisholm
  • 3,857
  • 1
  • 35
  • 29
-8

use external version.txt file with version, and prebuild step to publish this version in projects

Alex Zharnasek
  • 519
  • 5
  • 9