Configuration
Configure the proxy generator by adding MSBuild properties to your .csproj file.
Required Configuration
<PropertyGroup>
<CratisProxiesOutputPath>$(MSBuildThisFileDirectory)../Web</CratisProxiesOutputPath>
</PropertyGroup>
CratisProxiesOutputPath: Specifies where the generated TypeScript files will be written. This should typically point to your frontend project directory.
Optional Configuration
<PropertyGroup>
<CratisProxiesSegmentsToSkip>1</CratisProxiesSegmentsToSkip>
<CratisProxiesSkipOutputDeletion>true</CratisProxiesSkipOutputDeletion>
<CratisProxiesSkipCommandNameInRoute>false</CratisProxiesSkipCommandNameInRoute>
<CratisProxiesSkipQueryNameInRoute>false</CratisProxiesSkipQueryNameInRoute>
<CratisProxiesApiPrefix>api</CratisProxiesApiPrefix>
<CratisProxiesSkipFileIndexTracking>false</CratisProxiesSkipFileIndexTracking>
<CratisProxiesSkipIndexGeneration>false</CratisProxiesSkipIndexGeneration>
<CratisProxiesUseSourceFileAsOutputFile>false</CratisProxiesUseSourceFileAsOutputFile>
</PropertyGroup>
Configuration Options Reference
| Property | Default | Description |
|---|---|---|
CratisProxiesOutputPath |
(Required) | The output directory for generated TypeScript files |
CratisProxiesSegmentsToSkip |
0 |
Number of namespace segments to skip when creating the folder structure |
CratisProxiesSkipOutputDeletion |
true |
When true (default), the generator uses incremental generation — only changed files are updated and stale files are removed automatically. Set to false to force deletion of the entire output directory on every build. See Output Deletion Behavior below. |
CratisProxiesSkipCommandNameInRoute |
false |
When true, excludes the command name from the generated route for command endpoints |
CratisProxiesSkipQueryNameInRoute |
false |
When true, excludes the query name from the generated route for query endpoints |
CratisProxiesApiPrefix |
api |
The API prefix used in generated routes |
CratisProxiesSkipFileIndexTracking |
false |
When true, disables file index tracking for incremental cleanup |
CratisProxiesSkipIndexGeneration |
false |
When true, skips generating index.ts files for directories |
CratisProxiesUseSourceFileAsOutputFile |
false |
When true, groups all TypeScript types from the same C# source file into a single .ts file named after the source file |
Output Deletion Behavior
By default (CratisProxiesSkipOutputDeletion=true), the proxy generator uses incremental generation:
- Only files whose content has changed are written to disk — timestamps of unchanged files are preserved
- File index tracking automatically removes orphaned files from renamed/deleted commands or queries
- Build times are faster as only necessary files are regenerated
- Generated proxies committed to the repository keep their original timestamps when another developer builds the solution
This default is suitable for virtually all projects, including those that mix generated proxies with other source files.
To force full regeneration (deletes the entire output directory on every build), set:
<PropertyGroup>
<CratisProxiesSkipOutputDeletion>false</CratisProxiesSkipOutputDeletion>
</PropertyGroup>
When output deletion is enabled:
- All proxies are regenerated on every build
- Any manual files in the output directory will be deleted
- Build times may be longer as everything is recreated each time
- Committed proxy files will always appear as modified after a build
Recommendation: Keep the default true for incremental generation. Only set to false if you specifically need a guaranteed clean state and understand that all proxy timestamps will be updated on every build.
Namespace Segment Skipping
The CratisProxiesSegmentsToSkip property is particularly useful in multi-project solutions with consistent naming conventions.
For example, if you have a folder structure like:
<Your Root Folder>
|
├── Api
│ └── MyFeature
├── Domain
│ └── MyFeature
├── Events
│ └── MyFeature
└── Read
└── MyFeature
And corresponding namespaces like Api.MyFeature, Domain.MyFeature, Read.MyFeature, you might want to skip the first segment (Api, Domain, Read) to create a unified structure in your frontend. Setting CratisProxiesSegmentsToSkip to 1 would generate:
MyFeature/
├── commands/
└── queries/
Instead of:
Domain/
└── MyFeature/
└── commands/
Read/
└── MyFeature/
└── queries/
Route Name Configuration
The CratisProxiesSkipCommandNameInRoute and CratisProxiesSkipQueryNameInRoute properties allow you to control whether the command or query type names are included in the generated routes.
By default, both properties are false, meaning type names are included in routes:
- Command
CreateOrderCommand→/api/orders/create-order-command - Query
GetOrdersQuery→/api/orders/get-orders-query
When set to true, the type names are excluded:
- Command
CreateOrderCommand→/api/orders - Query
GetOrdersQuery→/api/orders
Automatic Conflict Detection
When CratisProxiesSkipCommandNameInRoute or CratisProxiesSkipQueryNameInRoute is set to true, the proxy generator automatically detects route conflicts. If multiple commands or queries exist in the same namespace (after skipping segments), the type/method name is automatically included in the route to prevent collisions.
This conflict detection ensures that:
- Routes remain clean when there's only one command/query in a namespace
- Route conflicts are automatically resolved by including type names when needed
- The generated proxy routes match the runtime endpoint mapping behavior exactly
Examples:
Single command in namespace MyApp.Orders.Commands:
CreateOrderCommand → /api/orders
Multiple commands in namespace MyApp.Orders.Commands:
CreateOrderCommand → /api/orders/create-order-command
UpdateOrderCommand → /api/orders/update-order-command
DeleteOrderCommand → /api/orders/delete-order-command
Example Configuration:
<PropertyGroup>
<!-- Include command names but exclude query names from routes -->
<CratisProxiesSkipCommandNameInRoute>false</CratisProxiesSkipCommandNameInRoute>
<CratisProxiesSkipQueryNameInRoute>true</CratisProxiesSkipQueryNameInRoute>
</PropertyGroup>
This allows for more granular control over API route generation, which can be particularly useful when you want cleaner URLs for queries while keeping explicit command names.
Source File Output
By default, the proxy generator creates one TypeScript file per type (e.g., CreateAccount.ts, UpdateAccount.ts). When multiple C# types are defined in the same source file, enabling CratisProxiesUseSourceFileAsOutputFile groups them all into a single TypeScript file named after the C# source file.
<PropertyGroup>
<CratisProxiesUseSourceFileAsOutputFile>true</CratisProxiesUseSourceFileAsOutputFile>
</PropertyGroup>
For example, if you have a C# file AccountCommands.cs containing:
public class CreateAccount { ... }
public class UpdateAccount { ... }
public class DeleteAccount { ... }
With the default behavior, three separate files are generated:
AccountCommands/
├── CreateAccount.ts
├── UpdateAccount.ts
└── DeleteAccount.ts
With CratisProxiesUseSourceFileAsOutputFile=true, all types from the same source file are combined into one:
AccountCommands/
└── AccountCommands.ts ← Contains CreateAccount, UpdateAccount, and DeleteAccount
This is particularly useful when you want your TypeScript proxy structure to mirror your C# project's file organization.
Note: This feature requires that the project is built with debug symbols (PDB files). Ensure the PDB file is available alongside the compiled assembly. If PDB information is not available, the generator falls back to generating individual files per type.
CLI Usage
When using the proxy generator CLI directly:
proxygenerator assembly.dll output-path --use-source-file-as-output-file
Advanced Configuration
For more complex scenarios, you can combine multiple configuration options:
<PropertyGroup>
<!-- Output to a specific frontend directory -->
<CratisProxiesOutputPath>$(MSBuildThisFileDirectory)../../Frontend/src/api</CratisProxiesOutputPath>
<!-- Skip Domain/Read prefixes in namespaces -->
<CratisProxiesSegmentsToSkip>1</CratisProxiesSegmentsToSkip>
<!-- Use a custom API prefix -->
<CratisProxiesApiPrefix>v1</CratisProxiesApiPrefix>
<!-- Don't delete existing files (useful for debugging) -->
<CratisProxiesSkipOutputDeletion>true</CratisProxiesSkipOutputDeletion>
</PropertyGroup>
This configuration would:
- Generate proxies in the
Frontend/src/apidirectory - Skip the first namespace segment when creating folders
- Use
v1instead ofapiin routes - Preserve any existing files in the output directory
Troubleshooting
Common Issues
- No proxies generated: Ensure the NuGet package is referenced and the output path is correctly configured
- Missing types: Complex types need to be public and discoverable by the generator
- Wrong folder structure: Adjust
CratisProxiesSegmentsToSkipto match your desired output structure - Build errors: Check that the target framework matches between your project and the proxy generator
Debugging
Enable detailed MSBuild logging to see the proxy generation process:
dotnet build -v detailed
Look for messages starting with "MSBuildProjectDirectory", "OutputPath", and "ProxyGenerator base directory" to verify the configuration is correct.