dotnet-add-content is a custom .NET CLI tool that helps you add content file includes to .csproj or .props files. It supports inline additions, reusable props files, and automatic import wiring.
Most dotnet commands let you create and configure projects from the command line. However, there is no built-in way to include content files like images, CSVs, or configuration files in your build without manually editing the .csproj.
This tool fills that gap by providing a clean and scriptable way to manage content includes using a simple CLI workflow.
You can use it to include static files like images, data files, and embedded assets in your project in a consistent and maintainable way.
- ✅ Add
<None Include="...">entries directly to.csproj(inline) - ✅ Generate or update
.propsfiles with shared content includes - ✅ Automatically import
.propsfiles into.csproj - ✅ Supports glob patterns (
data/**/*.csv,*.json,docs/file?.md, etc.) - ✅ Smart behavior: skip duplicates or use
--overwriteto regenerate - ✅ Fully validated CLI with rich error messages
- ✅ Friendly with MSBuild and NuGet packing
Say you're bootstrapping a new .NET project with a test project and some data files in a /data/ folder. You want those files copied to your test output directory automatically.
You might run:
dotnet new sln -n MyApp
dotnet new console -n MyApp.App
dotnet new xunit -n MyApp.Tests
dotnet sln add MyApp.App
dotnet sln add MyApp.Tests
dotnet add MyApp.Tests reference MyApp.AppThen manually edit your .csproj:
<!-- Inside MyApp.Tests.csproj -->
<ItemGroup>
<None Include="..\data\**\*.csv">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>data\%(RecursiveDir)%(Filename)%(Extension)</Link>
</None>
</ItemGroup>This works, but requires error-prone hand editing of project files.
Run the same setup:
dotnet new sln -n MyApp
dotnet new console -n MyApp.App
dotnet new xunit -n MyApp.Tests
dotnet sln add MyApp.App
dotnet sln add MyApp.Tests
dotnet add MyApp.Tests reference MyApp.AppThen instead of editing XML, just run:
dotnet add-content --project MyApp.Tests --include "../data/**/*.csv"This safely injects the correct <ItemGroup> into MyApp.Tests.csproj and ensures:
- ✅ Files are copied to
bin/at build time - ✅ Paths are linked with folder structure intact
- ✅ Everything is reproducible in CI/CD or onboarding scripts
When working in a multi-project solution, you might have multiple .csproj files that need to reference the same assets — for example, shared documentation, test resources, or config files.
You’d typically:
-
Create a
.propsfile manually:<!-- SharedContent.props --> <Project> <ItemGroup> <None Include="shared-assets/**/*.json"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <Link>%(RecursiveDir)%(Filename)%(Extension)</Link> </None> </ItemGroup> </Project>
-
Then manually import it into each
.csproj:<Import Project="SharedContent.props" />
This process is tedious and error-prone, especially across many projects.
You can do it all from the command line:
dotnet add-content --file SharedContent.props --include "shared-assets/**/*.json"Then import it into any project:
dotnet add-content --project ProjectA --file SharedContent.props
dotnet add-content --project ProjectB --file SharedContent.propsOr do both in one step:
dotnet add-content --project ProjectA --file SharedContent.props --include "shared-assets/**/*.json"This will:
- ✅ Create or update the shared
.propsfile - ✅ Append the new include if not already present
- ✅ Import it into the project if not already included
Using .props files this way keeps your content declarations DRY and your project files clean — perfect for scalable or enterprise-grade solutions with lots of shared data patterns.
Install globally from NuGet:
dotnet tool install --global dotnet-add-content✅ Requires .NET 8 SDK or later
dotnet add-content --project MyApp.csproj --include "assets/**/*.json"Adds this:
<ItemGroup>
<None Include="assets/**/*.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
</None>
</ItemGroup>dotnet add-content --file Shared.props --include "docs/**/*.md"Creates or updates:
<Project>
<ItemGroup>
<None Include="docs/**/*.md">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
</None>
</ItemGroup>
</Project>Use --overwrite to regenerate the file:
dotnet add-content --file Shared.props --include "docs/**/*.md" --overwritedotnet add-content --project MyLib.csproj --file Shared.propsAdds:
<Import Project="Shared.props" />If the import already exists, it will not be duplicated.
dotnet add-content --project MyApp.csproj --file Shared.props --include "resources/*.json"- Adds or updates the
.propsfile - Adds
<Import>to your.csproj
dotnet testIncludes full coverage for:
- 🔧 Inline and props editing
- 🧠 Smart CLI validation rules
- 🌀 Idempotent glob appends and import deduplication
⚠️ Error handling and invalid usage
This is useful when developing or testing local changes before publishing.
dotnet tool uninstall -g dotnet-add-contentdotnet pack -c ReleaseGenerates:
./DotnetAddContent/bin/Release/dotnet-add-content.1.0.0.nupkg
dotnet tool install --global --add-source ./DotnetAddContent/bin/Release dotnet-add-content✅ Will run using .NET 9 if available, or fallback to .NET 8 (thanks to <RollForward>Major</RollForward>)
dotnet add-content --help🎉 See the full help output and usage examples.
We welcome PRs, suggestions, and feedback!
To get started:
git clone https://github.com/ashergarland/dotnet-add-content.git
cd dotnet-add-content
dotnet build
dotnet testMIT License © 2025 Asher Garland View License
📦 nuget.org/packages/dotnet-add-content
This project uses GitHub Actions to automatically publish to nuget.org when a new version is tagged.
-
A GitHub Actions secret
NUGET_API_KEYmust be configured in the repo:- Create an API key on nuget.org
- Scope it to
dotnet-add-contentonly - Add it as a GitHub secret with name:
NUGET_API_KEY
Bump your version in the .csproj, then:
git commit -am "release: v1.0.1"
git tag v1.0.1
git push origin main --tagsThis will:
- Run tests
- Build and pack the tool
- Push to NuGet using your API key
dotnet tool install -g dotnet-add-contentwill get the latest published version- The CLI targets
.NET 8+and uses<RollForward>Major</RollForward>so it works on .NET 9+
Built with:
- System.CommandLine
System.Xml.Linqfor safe.csprojand.propsediting