MSBuild Reference Swapping¶
This document explains how to use the MSBuild Reference Swap System to switch between PackageReference and ProjectReference dependencies in SAIF Platform projects.
Overview¶
The reference swap system allows developers to easily switch between using NuGet packages and local project references during development. This is particularly useful for:
- Development: Use local project references to debug and develop across multiple SAIF platform components
- CI/CD: Use package references for stable builds and deployments
- Testing: Quickly switch between modes to test different scenarios
How It Works¶
The system uses MSBuild targets to transform ProjectOrPackageReference items into either PackageReference or ProjectReference items based on a boolean property.
Key Components¶
UseProjectReferenceproperty: Controls the reference mode (default:false)ProjectOrPackageReferenceitems: New item type that can resolve to either package or project referencesDirectory.Build.targets: Contains the MSBuild logic to perform the transformation- Automatic path generation: Projects are found using a configurable path pattern
Usage¶
Basic Usage¶
- Replace PackageReference with Reference: In your
.csprojfile, replace:
With:
- Use package references (default):
- Use project references:
Project Structure Requirements¶
The system expects SAIF platform projects to follow this structure:
src/dotnet/
├── SAIF.Platform.Authentication/
│ └── src/SAIF.Platform.Authentication/
│ └── SAIF.Platform.Authentication.csproj
├── SAIF.Platform.Kiota.HttpClientLibrary/
│ └── src/SAIF.Platform.Kiota.HttpClientLibrary/
│ └── SAIF.Platform.Kiota.HttpClientLibrary.csproj
└── ...
Path Pattern Configuration¶
The default path pattern is ..\..\..\{0}\src\{0}\{0}.csproj, which resolves from a project directory like:
- From:
SAIF.Platform.Kiota.HttpClientLibrary\src\SAIF.Platform.Kiota.HttpClientLibrary\ - To:
SAIF.Platform.Authentication\src\SAIF.Platform.Authentication\SAIF.Platform.Authentication.csproj
You can override the path pattern by setting the ReferenceProjectPathPattern property:
<PropertyGroup>
<ReferenceProjectPathPattern>custom\path\pattern\{0}.csproj</ReferenceProjectPathPattern>
</PropertyGroup>
Migration Guide¶
Step 1: Identify SAIF Platform Dependencies¶
Find all SAIF platform package references in your project:
Step 2: Replace with Reference Items¶
Change these to use the new ProjectOrPackageReference item type:
<!-- Before -->
<ItemGroup>
<PackageReference Include="Microsoft.Kiota.Abstractions" Version="1.19.1" />
<PackageReference Include="SAIF.Platform.Authentication" Version="1.0.31" />
</ItemGroup>
<!-- After -->
<ItemGroup>
<PackageReference Include="Microsoft.Kiota.Abstractions" Version="1.19.1" />
<ProjectOrPackageReference Include="SAIF.Platform.Authentication" Version="1.0.31" />
</ItemGroup>
Step 3: Test Both Modes¶
Verify both modes work correctly:
# Test package mode
dotnet clean
dotnet restore
dotnet build -p:UseProjectReference=false
# Test project mode (ensure referenced projects are restored first)
dotnet clean
dotnet build -p:UseProjectReference=true
Troubleshooting¶
Project Not Found Warnings¶
If you see warnings like:
Project not found for 'SAIF.Platform.Authentication' at '...\path\...' - falling back to package reference
Solutions:
- Verify the project exists at the expected path
- Check that the path pattern is correct for your project structure
- Use an explicit
ProjectPathattribute if needed - Ensure the referenced project has been restored
Duplicate PackageReference Warnings¶
This should not occur with the current implementation. If you see duplicate warnings:
- Clean the project:
dotnet clean - Check for any remaining
PackageReferenceitems for the same package - Verify you're not mixing
ProjectOrPackageReferenceandPackageReferencefor the same package
Build Errors in Referenced Projects¶
When using UseProjectReference=true, if referenced projects fail to build:
- Ensure all referenced projects have been restored:
dotnet restore - Build referenced projects individually to identify specific issues
- Check that all projects target compatible frameworks
Examples¶
Example 1: Basic Migration¶
Before (SAIF.Platform.Kiota.HttpClientLibrary.csproj):
<ItemGroup>
<PackageReference Include="Microsoft.Kiota.Abstractions" Version="1.19.1" />
<PackageReference Include="Microsoft.Kiota.Http.HttpClientLibrary" Version="1.19.1" />
<PackageReference Include="SAIF.Platform.Authentication" Version="1.0.31" />
</ItemGroup>
After:
<ItemGroup>
<PackageReference Include="Microsoft.Kiota.Abstractions" Version="1.19.1" />
<PackageReference Include="Microsoft.Kiota.Http.HttpClientLibrary" Version="1.19.1" />
<ProjectOrPackageReference Include="SAIF.Platform.Authentication" Version="1.0.31" />
</ItemGroup>
Example 2: Multiple SAIF Platform References¶
<ItemGroup>
<!-- External packages remain as PackageReference -->
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<!-- SAIF Platform packages use Reference for swappable mode -->
<ProjectOrPackageReference Include="SAIF.Platform.Authentication" Version="1.0.31" />
<ProjectOrPackageReference Include="SAIF.Platform.Azure" Version="1.0.31" />
<ProjectOrPackageReference Include="SAIF.Platform.EntityFramework" Version="1.0.31" />
</ItemGroup>
Example 3: Custom Path Pattern¶
<PropertyGroup>
<ReferenceProjectPathPattern>..\..\{0}\{0}.csproj</ReferenceProjectPathPattern>
</PropertyGroup>
<ItemGroup>
<ProjectOrPackageReference Include="SAIF.Platform.Authentication" Version="1.0.31" />
</ItemGroup>
Best Practices¶
-
Keep external packages as PackageReference: Only use
ProjectOrPackageReferencefor SAIF platform packages that you might want to develop against locally -
Use consistent patterns: Stick to the standard SAIF project structure when possible to avoid custom path patterns
-
Test both modes: Always verify that your project builds correctly in both package and project reference modes
-
Document dependencies: If your project requires specific SAIF platform projects to be available locally, document this in your README
-
CI/CD considerations: Use
UseProjectReference=falsein CI/CD pipelines unless you specifically need to build against local projects
MSBuild Target Details¶
The system works by implementing a target that runs before CollectPackageReferences and Restore:
- When
UseProjectReference=true: - Generates candidate project paths for each
ProjectOrPackageReferenceitem - Checks if the project files exist using
Exists() - Adds
ProjectReferenceitems for found projects - Falls back to
PackageReferencefor missing projects -
Removes original
ProjectOrPackageReferenceitems -
When
UseProjectReference=false: - Converts all
ProjectOrPackageReferenceitems directly toPackageReferenceitems - Removes original
ProjectOrPackageReferenceitems
The target is designed to be safe and provide clear feedback about what transformations are occurring.