Browse Source

Add ABP Framework 'Hidden Magic' article

Add a new community article with a cover image documenting ABP Framework's default conventions and behaviors. Adds docs/en/Community-Articles/2026-02-19-ABP-Framework-Hidden-Magic/post.md and images/cover.png; the article outlines 30+ automatic features (service registration, validation, UOW, auditing, Mapperly, outbox, event handling, virtual file system, Swagger, tenant resolution, etc.) to help developers understand what 'just works' in ABP and how to customize or disable defaults.
pull/24897/head
Enis Necipoglu 2 months ago
parent
commit
02ac6b00a0
  1. BIN
      docs/en/Community-Articles/2026-02-19-ABP-Framework-Hidden-Magic/images/cover.png
  2. 498
      docs/en/Community-Articles/2026-02-19-ABP-Framework-Hidden-Magic/post.md

BIN
docs/en/Community-Articles/2026-02-19-ABP-Framework-Hidden-Magic/images/cover.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 MiB

498
docs/en/Community-Articles/2026-02-19-ABP-Framework-Hidden-Magic/post.md

@ -0,0 +1,498 @@
# ABP Framework's Hidden Magic: Things That Just Work Without You Knowing
The ABP Framework is famous for its Convention-over-Configuration approach, which means a lot of things work automatically without explicit configuration. In this article, I'll uncover these "hidden magics" that make ABP so powerful but often go unnoticed by developers.
---
## 1. Automatic Service Registration Without Any Attributes
**The Magic:** Any class implementing `ITransientDependency`, `ISingletonDependency`, or `IScopedDependency` is automatically registered with the corresponding lifetime.
```csharp
// This is automatically registered as Transient - no configuration needed!
public class MyService : IMyService, ITransientDependency
{
public void DoSomething() { }
}
```
**Where it happens:** `Volo.Abp.Core/DependencyInjection/ConventionalRegistrarBase.cs`
The framework scans all assemblies and automatically determines service lifetime from class hierarchy. This is why you rarely need to manually register services in ABP.
---
## 2. All Interfaces Are Exposed By Default
**The Magic:** When you register a service, it's automatically registered as both itself AND all its implemented interfaces.
```csharp
public class UserService : IUserService, IValidationInterceptor
{
// Registered as both IUserService AND IValidationInterceptor
// No ExposeServices attribute needed!
}
```
**Where it happens:** `Volo.Abp.Core/DependencyInjection/ExposedServiceExplorer.cs:9-14`
```csharp
private static readonly ExposeServicesAttribute DefaultExposeServicesAttribute =
new ExposeServicesAttribute
{
IncludeDefaults = true,
IncludeSelf = true
};
```
---
## 3. Automatic Validation on Every Method
**The Magic:** Every application service method parameters are automatically validated - you don't need to add `[Validate]` attributes.
**Where it happens:** `Volo.Abp.Validation/ValidationInterceptorRegistrar.cs`
The `ValidationInterceptor` is automatically added to the interceptor pipeline for all services. Every method call triggers automatic validation of input parameters.
---
## 4. Automatic Unit of Work Management
**The Magic:** Every database operation is automatically wrapped in a transaction. You don't need to explicitly configure unit of work for most scenarios.
**Where it happens:** The `UnitOfWorkInterceptor` is auto-registered and automatically:
- Begins transaction before method execution
- Commits on success
- Rolls back on exception
---
## 5. Auditing Is Enabled By Default
**The Magic:** Auditing is **ON** by default, even for anonymous users!
```csharp
public class AbpAuditingOptions
{
public AbpAuditingOptions()
{
IsEnabled = true; // Enabled by default!
IsEnabledForAnonymousUsers = true; // Anonymous users are audited!
HideErrors = true; // Errors are silently hidden
AlwaysLogOnException = true; // Exceptions always logged
}
}
```
**Where it happens:** `Volo.Abp.Auditing/AbpAuditingOptions.cs:73-91`
This means every entity change and service call is logged automatically unless explicitly disabled.
---
## 6. Security Logging Is Always On
**The Magic:** Security logging is enabled by default in ABP!
```csharp
public AbpSecurityLogOptions()
{
IsEnabled = true; // Hidden: ON by default!
}
```
Every authentication attempt, authorization failure, and security-relevant action is logged automatically.
---
## 7. Data Filters Are Enabled By Default
**The Magic:** `ISoftDelete` and `IMultiTenant` filters are **enabled by default**.
```csharp
// In DataFilter.cs - Line 103
_filter.Value = _options.DefaultStates.GetOrDefault(typeof(TFilter))?.Clone()
?? new DataFilterState(true); // true = enabled!
```
This means:
- Deleted entities are automatically filtered out
- Multi-tenant data is automatically isolated
You must explicitly **disable** these filters when you need to access all data:
```csharp
using (_dataFilter.Disable<IMultiTenant>())
{
// Query all tenants
}
```
---
## 8. Object Mapping (Mapperly - The New Standard)
**The Magic:** ABP now uses **Mapperly** instead of AutoMapper in new project templates. Any class using Mapperly attributes is automatically configured.
```csharp
// New ABP projects use Mapperly instead of AutoMapper
[MapperGenerator]
public partial class MyMapper : MapperBase
{
public partial UserDto MapToDto(User user);
public partial User MapToEntity(UserDto dto);
}
```
The mapping is done at **compile-time** (no reflection overhead), and it's automatically registered with ABP's `IObjectMapper`.
**Where it happens:** `Volo.Abp.Mapperly/AbpMapperlyConventionalRegistrar.cs`
```csharp
// Automatically discovers and configures all Mapperly mappers
context.Services.OnRegistered(context =>
{
if (typeof(MapperBase).IsAssignableFrom(context.ImplementationType))
{
// Register the mapper
}
});
```
**Migration Note:** If you're on an older project using AutoMapper, you can manually add `Volo.Abp.AutoMapper` package and configure it. However, new templates come with Mapperly out of the box.
---
## 9. Automatic Data Seed Contributor Discovery
**The Magic:** Any class implementing `IDataSeedContributor` is automatically discovered and executed on application startup.
```csharp
// Automatically discovered and run on startup!
public class MyDataSeeder : IDataSeedContributor
{
public Task SeedAsync(DataSeedContext context)
{
// Seed data here
}
}
```
**Where it happens:** `Volo.Abp.Data/AbpDataModule.cs:40-56`
---
## 10. Automatic Definition Provider Discovery
**The Magic:** These are all auto-discovered without any configuration:
- `ISettingDefinitionProvider` - Settings
- `IPermissionDefinitionProvider` - Permissions
- `IFeatureDefinitionProvider` - Features
- `INavigationProvider` - Navigation items
---
## 11. Automatic Widget Discovery
**The Magic:** Any class implementing `IWidget` is automatically registered and can be rendered in pages.
**Where it happens:** `Volo.Abp.AspNetCore.Mvc.UI.Widgets/AbpAspNetCoreMvcUiWidgetsModule.cs`
---
## 12. Remote Services Are Enabled By Default
**The Magic:** All API controllers have remote service functionality enabled by default:
```csharp
public class RemoteServiceAttribute : Attribute
{
public bool IsEnabled { get; set; } = true; // Enabled by default!
}
```
---
## 13. Permission Checks Are Automatic
**The Magic:** Every application service method is automatically protected. If you don't specify permissions, it still checks for login - no `[Authorize]` attribute needed!
---
## 14. Background Workers Auto-Registration
**The Magic:** Background workers are enabled by default, and any class implementing `IBackgroundWorker` or `IQuartzBackgroundWorker` is auto-registered.
---
## 15. Entity ID Generation
**The Magic:** ABP automatically detects the best ID generation strategy based on the entity type:
- `Guid` → Auto-generates GUID
- `int`/`long` → Database identity
- `string` → No auto-generation (must provide)
**Where it happens:** `Volo.Abp.Ddd.Domain/Entities/EntityHelper.cs`
---
## 16. Anti-Forgery Token Magic
**The Magic:** ABP automatically handles CSRF protection with these hardcoded values:
```csharp
// Blazor Client
private const string AntiForgeryCookieName = "XSRF-TOKEN";
private const string AntiForgeryHeaderName = "RequestVerificationToken";
```
---
## 17. Automatic Event Handler Discovery
**The Magic:** Any class implementing `IEventHandler<TEvent>` is automatically subscribed to handle events - no manual registration needed!
```csharp
// This handler is automatically registered when the assembly loads!
public class OrderCreatedHandler : IEventHandler<OrderCreatedEvent>
{
public Task HandleEventAsync(OrderCreatedEvent eventData)
{
// Handle the event - automatically subscribed!
}
}
```
---
## 18. Unit of Work Events - Automatic Save
**The Magic:** Events are not fired immediately - they're collected during the unit of work and fired at the end when everything succeeds!
```csharp
// In UnitOfWorkEventPublisher.cs
// Events are queued and published only when UOW successfully completes
await _localEventBus.PublishAsync(
entityChangeEvent,
onUnitOfWorkComplete: true // Wait for UOW to complete!
);
```
This ensures transactional consistency - if your UOW fails, no events are fired.
---
## 19. Distributed Event Bus - Outbox Pattern
**The Magic:** ABP implements the Outbox Pattern automatically for distributed events, ensuring no events are lost!
```csharp
// In DistributedEventBusBase.cs
// Events are stored in outbox table and processed reliably
foreach (var outboxConfig in AbpDistributedEventBusOptions.Outboxes.Values.OrderBy(x => x.Selector is null))
{
// Outbox processing happens automatically
}
```
---
## 20. Automatic Object Extension Properties
**The Magic:** Any property decorated with `[DisableAuditing]` is automatically excluded from audit logs without any configuration!
```csharp
// This property is automatically excluded from auditing
[DisableAuditing]
public string SecretData { get; set; }
```
---
## 21. Virtual File System
**The Magic:** ABP provides a virtual file system that merges embedded resources from all modules into a single virtual path!
```csharp
// Any file embedded as "EmbeddedResource" is accessible virtually
// No configuration needed for module authors!
```
**Where it happens:** `Volo.Abp.VirtualFileSystem/AbpVirtualFileSystemModule.cs`
This is how ABP modules include static files (CSS, JS, images) that work without copying to wwwroot.
---
## 22. Automatic JSON Serialization Settings
**The Magic:** ABP pre-configures JSON serialization with:
- Camel case property naming
- Null value handling
- Reference loop handling
- Custom converters for common types
All configured automatically.
---
## 23. Token-Based Configuration Magic
**The Magic:** Many settings support tokens that are resolved at runtime:
```csharp
// These tokens are automatically replaced
"ConnectionStrings": {
"Default": "Server=localhost;Database=MyApp_{TENANT_ID}"
}
```
- `{TENANT_ID}` - Replaced with current tenant ID
- `{USER_ID}` - Replaced with current user ID
- `{CURRENT_TIME}` - Replaced with current datetime
---
## 24. Localization Automatic Discovery
**The Magic:** All `.json` localization files in the application are automatically discovered and loaded:
```
/Localization/MyApp/
en.json
tr.json
de.json
```
No explicit registration needed - just add files and they're available!
---
## 25. Feature Checkers Work Automatically
**The Magic:** Features are checked automatically when calling application services.
**Where it happens:** `FeatureInterceptor` automatically validates feature requirements.
---
## 26. API Versioning Convention
**The Magic:** ABP automatically handles API versioning with sensible defaults:
- Default version: `1.0`
- Version from URL path: `/api/v1/...`
- Version from header: `Accept: application/json;v=1.0`
All configured automatically unless overridden.
---
## 27. Health Check Endpoints
**The Magic:** Health check endpoints are auto-registered:
- `/health` - Overall health status
- `/health/ready` - Readiness check
- `/health/live` - Liveness check
Includes automatic checks for:
- Database connectivity
- Cache availability
- External services
---
## 28. Swagger/OpenAPI Auto-Configuration
**The Magic:** If you reference `Volo.Abp.AspNetCore.Mvc.UI.Swagger`, Swagger UI is automatically generated with:
- All API endpoints documented
- Authorization support
- Versioning support
- XML documentation
No configuration needed beyond the package reference!
---
## 29. Tenant Resolution Priority Chain
**The Magic:** ABP automatically resolves tenants in this order (first match wins):
1. **Route** - From URL path (`/api/v1/[tenant]/...`)
2. **Query String** - From `__tenant` query parameter
3. **Header** - From `__tenant` header
4. **Cookie** - From `__tenant` cookie
5. **Subdomain** - From URL subdomain (`tenant.domain.com`)
---
## 30. Background Job Queue Magic
**The Magic:** Background jobs are automatically retried with exponential backoff:
```csharp
// Jobs are automatically:
// - Queued when published
// - Retried on failure (3 times default)
// - Delayed with exponential backoff
```
**Where it happens:** `Volo.Abp.BackgroundJobs/AbpBackgroundJobOptions.cs`
---
## Summary Table
| # | Feature | Default Behavior | You Need to Know |
|---|---------|-----------------|------------------|
| 1 | **Service Registration** | Auto by interface | Implement `ITransientDependency` |
| 2 | **Service Exposure** | Self + all interfaces | Default is generous |
| 3 | **Validation** | All methods validated | Happens automatically |
| 4 | **Unit of Work** | Transactional by default | Auto-commits/rollbacks |
| 5 | **Auditing** | Enabled + anonymous users | Can disable per entity/method |
| 6 | **Security Log** | Always on | Can configure what to log |
| 7 | **Soft Delete Filter** | Enabled by default | Must disable to query deleted |
| 8 | **Multi-Tenancy Filter** | Enabled by default | Must disable for host data |
| 9 | **Object Mapping** | Mapperly (compile-time) | Use `[MapperGenerator]` attribute |
| 10 | **Data Seeds** | Auto-discovery | Implement `IDataSeedContributor` |
| 11 | **Permissions** | Auto-discovery | Define via `PermissionDefinitionProvider` |
| 12 | **Settings** | Auto-discovery | Define via `ISettingDefinitionProvider` |
| 13 | **Features** | Auto-discovery | Define via `IFeatureDefinitionProvider` |
| 14 | **Widgets** | Auto-discovery | Implement `IWidget` |
| 15 | **Background Workers** | Auto-registration | Implement `IBackgroundWorker` |
| 16 | **Event Handlers** | Auto-discovery | Implement `IEventHandler<TEvent>` |
| 17 | **UOW Events** | Deferred execution | Transactional consistency |
| 18 | **Distributed Events** | Outbox pattern | Reliable messaging |
| 19 | **Virtual Files** | Module merging | No manual file copying |
| 20 | **JSON Settings** | Pre-configured | Works out of box |
| 21 | **Token Replacement** | Runtime resolution | Dynamic configuration |
| 22 | **Localization** | Auto-discovery | Just add JSON files |
| 23 | **Feature Checks** | Auto-intercepted | No manual checks |
| 24 | **API Versioning** | Default versioning | Convention-based |
| 25 | **Health Checks** | Auto-registered | Built-in monitoring |
| 26 | **Swagger** | Auto-generated | API documentation |
| 27 | **Tenant Resolution** | Multi-source chain | Flexible resolution |
| 28 | **Job Retries** | Auto with backoff | Reliability |
---
## Conclusion
ABP Framework's hidden magic is what makes it so productive to use. These conventions allow developers to focus on business logic rather than boilerplate configuration. However, understanding these defaults is crucial for:
1. **Debugging** - Knowing why certain behaviors happen
2. **Optimization** - Disabling what you don't need
3. **Security** - Understanding what's logged/audited by default
4. **Architecture** - Following the intended patterns
The next time something "just works" in ABP, there's likely a hidden convention behind it!
---
*What hidden ABP magic have you discovered? Share your findings in the comments!*
Loading…
Cancel
Save