Global exclusions allow you to configure a centralized list of property names that should be excluded from all generated DTOs by default. This feature is particularly useful for excluding common audit properties, internal tracking fields, or sensitive data across your entire project.
In your .csproj file, add the DtoGeneratorExclusions property with a comma- or semicolon-separated list of
property names. Names are trimmed, so whitespace around a separator is fine, and matching is case-sensitive
(the generator collects them into a HashSet<string> with the default ordinal comparer):
<PropertyGroup>
<DtoGeneratorExclusions>CreatedBy,UpdatedBy,CreatedAt,UpdatedAt</DtoGeneratorExclusions>
</PropertyGroup>That's it — no CompilerVisibleProperty item is needed in the consuming project. DKNet.EfCore.DtoGenerator ships its own .props file that already declares DtoGeneratorExclusions (and DtoGeneratorIgnoreComplexType) as CompilerVisibleProperty, and that .props file flows transitively to every project referencing the package.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)Generated</CompilerGeneratedFilesOutputPath>
<!-- Global exclusions for DTO generator -->
<DtoGeneratorExclusions>CreatedBy,UpdatedBy,CreatedAt,UpdatedAt</DtoGeneratorExclusions>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DKNet.EfCore.DtoGenerator" Version="*" /> <!-- use the current version -->
</ItemGroup>
</Project>using DKNet.EfCore.DtoGenerator;
// Entity with audit properties
public class Product
{
public Guid Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public DateTime CreatedAt { get; set; } // Globally excluded
public string CreatedBy { get; set; } // Globally excluded
public DateTime UpdatedAt { get; set; } // Globally excluded
public string UpdatedBy { get; set; } // Globally excluded
}
// DTO automatically excludes global properties
[GenerateDto(typeof(Product))]
public partial record ProductDto;
// Generated DTO will only include: Id, Name, Priceusing DKNet.EfCore.DtoGenerator;
public class Order
{
public Guid Id { get; set; }
public string OrderNumber { get; set; }
public decimal Amount { get; set; }
public string InternalNotes { get; set; }
public DateTime CreatedAt { get; set; } // Globally excluded
public string CreatedBy { get; set; } // Globally excluded
}
// Combine global exclusions with local exclusions
[GenerateDto(typeof(Order), Exclude = [nameof(Order.InternalNotes)])]
public partial record OrderDto;
// Generated DTO will exclude: CreatedAt, CreatedBy (global) + InternalNotes (local)
// Result: Id, OrderNumber, Amountusing DKNet.EfCore.DtoGenerator;
// Include specific properties, ignoring global exclusions
[GenerateDto(typeof(Product), Include = [
nameof(Product.Id),
nameof(Product.Name),
nameof(Product.CreatedAt) // Explicitly included despite being globally excluded
])]
public partial record ProductSummaryDto;
// Generated DTO will only include: Id, Name, CreatedAt| Scenario | Local Exclude | Local Include | Global Exclusions | Result |
|---|---|---|---|---|
| 1 | None | None | Applied | Global exclusions applied |
| 2 | Specified | None | Applied | Global + Local exclusions combined |
| 3 | None | Specified | Ignored | Only Include list properties |
| 4 | Specified | Specified | Error | Cannot use both Include and Exclude |
The list is not limited to hand-written [GenerateDto] records. A [RaisesEvent] convention form — the label
and label-less constructors, which compose their payload record's name instead of naming an existing one — has its
generated payload narrowed by DtoGeneratorExclusions exactly like the table above:
// <DtoGeneratorExclusions>CreatedBy,UpdatedBy,CreatedAt,UpdatedAt</DtoGeneratorExclusions>
using DKNet.EfCore.Abstractions.Events;
[RaisesEvent(EventOperations.Created)]
public class Customer { /* ... */ }
// CustomerCreatedEvent is generated without CreatedBy, UpdatedBy, CreatedAt, UpdatedAtThe same precedence applies: the declaration's own Exclude combines with the global list, and a non-empty
Include on the declaration replaces both. Exclude/Include on the type-naming form is a build error
(DKRAISEVT011) — that form's payload record owns its own shape through its own [GenerateDto] filters, which
are then subject to the matrix above.
The generator provides helpful diagnostics:
When you use the Include parameter with global exclusions configured, you'll receive an informational diagnostic:
Info DKDTOGEN005: DTO ProductSummaryDto: Using Include parameter ignores the 4 global exclusion(s). Only specified properties will be included.
This is informational only and doesn't indicate an error. It reminds you that the Include parameter takes precedence over global exclusions.
Exclude standard audit fields across all DTOs:
<DtoGeneratorExclusions>CreatedBy,CreatedAt,UpdatedBy,UpdatedAt,LastModifiedBy,LastModifiedOn</DtoGeneratorExclusions>Exclude internal system fields:
<DtoGeneratorExclusions>InternalId,RowVersion,IsDeleted,DeletedAt</DtoGeneratorExclusions>Exclude sensitive or security-related fields:
<DtoGeneratorExclusions>Password,PasswordHash,Salt,SecurityStamp,ConcurrencyToken</DtoGeneratorExclusions>- Reduced Boilerplate: No need to specify common exclusions on every DTO
- Consistency: Ensures audit/internal properties are consistently excluded
- Maintainability: Change exclusions in one place
- Flexibility: Override with
Includeparameter when needed - Type Safety: Compile-time enforcement ensures properties don't leak
Before (without global exclusions):
using DKNet.EfCore.DtoGenerator;
[GenerateDto(typeof(Product), Exclude = ["CreatedBy", "UpdatedBy", "CreatedAt", "UpdatedAt"])]
public partial record ProductDto;
[GenerateDto(typeof(Order), Exclude = ["CreatedBy", "UpdatedBy", "CreatedAt", "UpdatedAt"])]
public partial record OrderDto;
[GenerateDto(typeof(Customer), Exclude = ["CreatedBy", "UpdatedBy", "CreatedAt", "UpdatedAt"])]
public partial record CustomerDto;After (with global exclusions):
<!-- In .csproj -->
<DtoGeneratorExclusions>CreatedBy,UpdatedBy,CreatedAt,UpdatedAt</DtoGeneratorExclusions>using DKNet.EfCore.DtoGenerator;
[GenerateDto(typeof(Product))]
public partial record ProductDto;
[GenerateDto(typeof(Order))]
public partial record OrderDto;
[GenerateDto(typeof(Customer))]
public partial record CustomerDto;- Verify MSBuild property: Check your
.csprojfile usesDtoGeneratorExclusions(not an older/renamed variant) - Clean and rebuild: Delete
objandbinfolders - Check generated files: Look in
obj/Generatedfolder - Check build output: Look for DKDTOGEN diagnostics
If a globally excluded property appears in a DTO:
- Check if the DTO uses
Includeparameter (overrides global exclusions) - Verify property name matches exactly (case-sensitive)
- Ensure the property exists in the global exclusion list
- Start Small: Begin with common audit properties
- Document Decisions: Comment why certain properties are globally excluded
- Review Regularly: Periodically review if global exclusions still make sense
- Use Include Sparingly: Only override global exclusions when truly necessary
- Test Thoroughly: Verify DTOs don't expose sensitive data
Global exclusions are processed at compile-time, not runtime:
- ✅ No performance impact at runtime
- ✅ Same performance as local exclusions
- ✅ Results in smaller DTO classes
- ✅ Reduces generated code size
- DKNet.EfCore.DtoGenerator — the package's full reference
- EF Core packages index — where this page sits in the family
- Source Generator Documentation
- MSBuild Properties