versioning
assemblyinfo
software development
code management
.net

Shared AssemblyInfo for uniform versioning across the solution

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Keeping version numbers aligned across many .NET projects becomes painful if each project owns its own assembly metadata file. The classic solution was a shared AssemblyInfo.cs, but modern SDK-style projects often use Directory.Build.props or other MSBuild properties instead. The right approach depends on whether your solution uses older non-SDK projects or newer SDK-style ones.

The Classic Shared AssemblyInfo.cs Pattern

In older .NET Framework style solutions, each project often had its own Properties/AssemblyInfo.cs file with attributes such as AssemblyVersion and AssemblyFileVersion.

A shared file centralizes those attributes:

csharp
1using System.Reflection;
2
3[assembly: AssemblyCompany("Example Corp")]
4[assembly: AssemblyProduct("Example Suite")]
5[assembly: AssemblyVersion("2.3.0.0")]
6[assembly: AssemblyFileVersion("2.3.0.0")]
7[assembly: AssemblyInformationalVersion("2.3.0")]

You then include that file in multiple project files instead of duplicating the version attributes everywhere.

In a classic .csproj, that can look like this:

xml
1<ItemGroup>
2  <Compile Include="..\Shared\SharedAssemblyInfo.cs">
3    <Link>Properties\SharedAssemblyInfo.cs</Link>
4  </Compile>
5</ItemGroup>

This gives every project one shared source of version metadata.

Why Modern SDK-Style Projects Often Use MSBuild Properties Instead

In current .NET, SDK-style projects usually auto-generate assembly attributes from project properties. That means you often do not need a physical AssemblyInfo.cs file at all.

A solution-level Directory.Build.props file is frequently the cleaner answer:

xml
1<Project>
2  <PropertyGroup>
3    <Company>Example Corp</Company>
4    <Product>Example Suite</Product>
5    <Version>2.3.0</Version>
6    <AssemblyVersion>2.3.0.0</AssemblyVersion>
7    <FileVersion>2.3.0.0</FileVersion>
8    <InformationalVersion>2.3.0</InformationalVersion>
9  </PropertyGroup>
10</Project>

Every project under that directory tree inherits these values automatically unless it overrides them.

For many modern solutions, this is more maintainable than linking one shared source file.

Avoiding Duplicate Attribute Errors

A common issue appears when a project both auto-generates assembly metadata and also includes manual attributes. That produces duplicate assembly-attribute errors at build time.

If you want to keep a manual shared AssemblyInfo.cs in an SDK-style project, disable auto-generation:

xml
<PropertyGroup>
  <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>

That tells the SDK not to emit the same assembly attributes automatically.

Uniform Versioning in CI

Shared versioning becomes more powerful when the build pipeline controls the version number. For example, CI can inject a build number into Version or InformationalVersion while leaving assembly structure stable.

A simple pattern is:

  • keep base version metadata in Directory.Build.props
  • let CI override one or two properties during the build
  • avoid hand-editing version numbers across many projects

That scales much better than touching several AssemblyInfo.cs files by hand.

Which Approach Should You Use

Use a shared AssemblyInfo.cs when:

  • the solution still contains older project types
  • assembly attributes are already managed manually
  • you need one linked source file for compatibility reasons

Use Directory.Build.props or solution-level MSBuild properties when:

  • the projects are SDK-style
  • you want the simplest modern setup
  • you want versioning to integrate cleanly with CI and auto-generated metadata

The goal is not nostalgia for one file. The goal is one source of truth.

Common Pitfalls

A common mistake is mixing a shared AssemblyInfo.cs with SDK-generated attributes and then hitting duplicate attribute errors.

Another issue is sharing too much metadata. Some values such as product version should be uniform, but others such as assembly title may legitimately differ between projects.

Teams also sometimes centralize version numbers but forget package versioning, informational versioning, or CI-injected build metadata. Uniformity should include the full release story, not just one attribute.

Finally, do not keep using the old shared-file pattern automatically if the solution has already moved to SDK-style projects. MSBuild property-based versioning is often simpler.

Summary

  • A shared AssemblyInfo.cs is the classic way to centralize version metadata across older .NET projects.
  • SDK-style projects often work better with Directory.Build.props and generated assembly info.
  • Disable GenerateAssemblyInfo if you keep manual assembly attributes in SDK-style projects.
  • Centralized versioning is most effective when CI can override build-specific values.
  • Choose the one-source-of-truth mechanism that matches your project style, not just historical habit.

Course illustration
Course illustration

All Rights Reserved.