This guide provides a streamlined migration path from the community @nx-dotnet/core plugin to Nx official @nx/dotnet plugin.
Plugin Status
The
@nx-dotnet/coreplugin is deprecated in favor of the official@nx/dotnetplugin (available in Nx 22+), which is maintained by the Nx team and integrated directly into the Nx repository.
Why migrate?
The official @nx/dotnet plugin represents a natural evolution, building on lessons learned from the community plugin while embracing native .NET workflows:
- Project inference: Automatic detection of .NET projects without configuration with Nx inferred targets
- MSBuild integration: Direct use of Microsoft's APIs for accurate dependency analysis
- Native CLI first: Uses
dotnetcommands directly instead of custom wrappers - Minimal abstraction: Simpler implementation with fewer dependencies
This results in a faster, and more reliable .NET plugin.
Prerequisites
Before starting the migration:
- [ ] Upgrade to .NET SDK 8.0 or later (required)
- [ ] Locate your current @nx-dotnet/core configuration (see below)
- [ ] Review any custom generators and executors you're using
- [ ] Ensure your projects build successfully with current setup
Locating your configuration
The @nx-dotnet/core plugin configuration can be in one of two places:
nx.json
{
"plugins": [
{
"plugin": "@nx-dotnet/core",
"options": {
"inferredTargets": { ... },
"solutionFile": "...",
// ... other options
}
}
]
}
.nx-dotnet.rc.json
{
"inferredTargets": { ... },
"solutionFile": "...",
// ... other options
}
No Configuration?
If you don't have custom configuration in either location, that's fine! The plugin works with defaults, and migration will be even simpler.
Migration steps
1. Install @nx/dotnet
nx add @nx/dotnet
This automatically:
- Adds
@nx/dotnetas a dependency - Registers the plugin in
nx.json - Configures target inputs
- Updates
.gitignore
2. Remove @nx-dotnet/core
npm uninstall @nx-dotnet/core @nx-dotnet/utils @nx-dotnet/dotnet
Clean up the relevant workspace configurations:
- Remove
@nx-dotnet/corefrom thepluginsarray innx.json(if present) - Delete
.nx-dotnet.rc.json(if it exists)
3. Migrate plugin configuration
Move any customized target configurations from your @nx-dotnet/core config to the new @nx/dotnet plugin options.
Before (in nx.json or .nx-dotnet.rc.json):
{
"inferredTargets": {
"build": "build",
"test": {
"targetName": "test:dotnet",
"cache": false
}
}
}
After (in nx.json):
// nx.json
{
"plugins": [
{
"plugin": "@nx/dotnet",
"options": {
"build": {
"targetName": "build"
},
"test": {
"targetName": "test:dotnet"
}
}
}
]
}
4. clear cache and verify
nx reset
nx graph
The nx graph command should show all your .NET projects with their dependencies correctly detected. If you encounter any issues, see the Troubleshooting section below.
Key workflow changes
Here's what changes in your day-to-day usage with the new @nx/dotnet plugin:
| Task | Old (@nx-dotnet/core) | New (@nx/dotnet) |
|---|---|---|
| Create application | nx g @nx-dotnet/core:app my-api | dotnet new webapi -n MyApi |
| Create library | nx g @nx-dotnet/core:lib my-lib | dotnet new classlib -n MyLib |
| Add project reference | nx g @nx-dotnet/core:project-reference --source A --target B | dotnet add reference ../B/B.csproj |
| Add NuGet package | nx g @nx-dotnet/core:nuget-reference | dotnet add package PackageName |
| Build project | nx build my-api | nx build my-api ✅ (same) |
| Run tests | nx test my-api | nx test my-api ✅ (same) |
| Serve/watch | nx serve my-api | dotnet watch run (or configure custom target) |
Default targets generated
The plugin automatically creates these targets for .NET projects:
| Target | When Created | Command |
|---|---|---|
build | All projects | dotnet build --no-restore --no-dependencies |
test | Test projects only | dotnet test --no-build --no-restore |
restore | All projects | dotnet restore |
clean | All projects | dotnet clean |
publish | Executable projects | dotnet publish |
pack | Library projects | dotnet pack |
Adding back missing targets
The serve and format targets are not automatically created. serve defaults to a target named watch now. To run it, you'd need to run nx run my-api:watch run. To configure the watch target to act like serve, you could set the following in nx.json:
// nx.json
{
"plugins": [
{
"plugin": "@nx/dotnet",
"options": {
"watch": {
"targetName": "serve",
"args": ["run"]
}
}
}
]
}
The format target is not present by default. You should add it as a custom target if desired.
Advanced migration scenarios
Migrating from explicit executor configurations
If you have project.json files that explicitly configure @nx-dotnet/core executors, you'll need to update them to use command targets.
Before (project.json):
// project.json
{
"name": "my-api",
"targets": {
"build": {
"executor": "@nx-dotnet/core:build",
"options": {
"configuration": "Release",
"noDependencies": true
}
},
"test": {
"executor": "@nx-dotnet/core:test",
"options": {
"testProject": "MyApi.Tests.csproj"
}
},
"serve": {
"executor": "@nx-dotnet/core:serve",
"options": {
"project": "MyApi.csproj"
}
}
}
}
After (project.json):
// project.json
{
"name": "my-api",
"targets": {
"build": {
"command": "dotnet build",
"options": {
"cwd": "{projectRoot}",
"args": ["--configuration", "Release", "--no-dependencies"]
}
},
"test": {
"command": "dotnet test MyApi.Tests.csproj",
"options": {
"cwd": "{projectRoot}"
}
},
"serve": {
"command": "dotnet watch run",
"options": {
"cwd": "{projectRoot}"
}
}
}
}
Automatic Target Inference
In most cases, you can delete these
project.jsonfiles entirely. The @nx/dotnet plugin will automatically infer the correct targets based on your.csprojfiles. Only keep customproject.jsonconfigurations if you need non-standard options.
Migrating from inferProjects: false
If you previously set inferProjects: false in your @nx-dotnet/core config, this option no longer exists in @nx/dotnet. The new plugin always infers projects automatically.
Why this changed:
- Project inference is a core feature of how Nx plugins work
- Manual project management doesn't align with Nx preferred automatic detection model
- Maintaining explicit project configurations is error-prone
Migration path:
If you disabled inference to exclude certain projects:
- Use the
excludeproperty in the plugin configuration:// nx.json { "plugins": [ { "plugin": "@nx/dotnet", "exclude": ["legacy-projects/**", "temp-projects/**"] } ] }
- Use the
If you disabled inference to use explicit project.json files:
- The new plugin will still detect your projects via
.csprojfiles - You can keep
project.jsonfiles to customize targets, but they're optional - Consider removing them to use the automatically inferred targets
- The new plugin will still detect your projects via
Configuration changes
Module boundaries → Nx conformance
If you used moduleBoundaries in your @nx-dotnet/core config, you may want to migrate to Nx Conformance rules
The script used to evaluate module boundaries is missing several features from the eslint and conformance implementations, and is not present in the new plugin. If you wish to continue using it, you'll need to inline the implementation in your repository and update the path in Directory.build.targets. Otherwise, you should remove the target from Directory.build.targets.
NuGet package management
Replace the sync generator with MSBuild's Central Package Management.
Create Directory.Packages.props at workspace root:
// Directory.Packages.props
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.0" />
</ItemGroup>
</Project>
Update project files to remove version attributes:
- <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
+ <PackageReference Include="Newtonsoft.Json" />
Testing the migration
Run these commands to verify everything works:
# Clear cache
nx reset
# Verify project detection
nx show projects
# Test builds
nx run-many -t build
# Test affected builds
nx affected -t build
# Run tests
nx run-many -t test
Troubleshooting
Projects not detected after migration
Symptom: Some .NET projects don't appear in nx show projects
Solution:
- Ensure project files have
.csproj,.fsproj, or.vbprojextensions - Check that the plugin is registered in
nx.json - Run
nx resetto clear the cache
"Could not find project reference" build error
Symptom: Build fails with "Could not find project reference"
Solution:
- Verify the referenced project exists in the workspace
- Ensure build targets have
"dependsOn": ["^build"](plugin adds this automatically) - Check that project references in
.csprojfiles use correct relative paths - Run
nx resetto clear stale cache
Missing Targets (test, pack, publish)
Symptom: Expected targets like test or pack don't show up
Solution:
test: Only created for projects withIsTestProjectproperty orMicrosoft.NET.Test.Sdkpackagepack: Only created for library projects (not executables)publish: Only created for executable projects (OutputType="Exe")- Use
nx show project my-projectto see all available targets
Project name mismatch after migration
Symptom: Project names don't match expectations
Solution: Add a Name property to your .csproj file under the Nx property group:
<PropertyGroup>
<Nx>
<Name>my-custom-name</Name>
</Nx>
</PropertyGroup>
Next steps
After completing the migration:
- Review the incremental builds guide to understand how
--no-dependenciesoptimizes builds - Configure Nx Cloud for improved repo experience for your team and CI
- Set up custom targets for
serve,lint, or other specialized tasks as needed - Update CI/CD pipelines to ensure .NET SDK 8.0+ is installed